ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

自定义 ocelot 中间件输出自定义错误信息

2021-02-07 08:32:19  阅读:223  来源: 互联网

标签:errors 自定义 中间件 错误信息 ocelotBuilder ocelot httpContext


自定义 ocelot 中间件输出自定义错误信息

Intro

ocelot 中默认的 Response 中间件在出错的时候只会设置 StatusCode 没有具体的信息,想要展示自己定义的错误信息的时候就需要做一些自定义了,对 ocelot 中的 Response 中间件做了一些小改动,实现了输出自定义错误信息的功能。

Implement

实现起来其实也很简单,原来的有错误的时候,只设置了 Response 的 StatusCode,我们只需要加一下输出错误信息就可以了,错误信息的格式完全可以自定义,实现代码如下:

public class CustomResponseMiddleware : Ocelot.Middleware.OcelotMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IHttpResponder _responder;
    private readonly IErrorsToHttpStatusCodeMapper _codeMapper;

    public CustomResponseMiddleware(
        RequestDelegate next,
        IHttpResponder responder,
        IErrorsToHttpStatusCodeMapper codeMapper,
        IOcelotLoggerFactory loggerFactory)
        : base(loggerFactory.CreateLogger<UrlBasedAuthenticationMiddleware>())
    {
        _next = next;
        _responder = responder;
        _codeMapper = codeMapper;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        await _next.Invoke(httpContext);
        if (httpContext.Response.HasStarted)
            return;

        var errors = httpContext.Items.Errors();
        if (errors.Count > 0)
        {
            Logger.LogWarning($"{errors.ToErrorString()} errors found in {MiddlewareName}. Setting error response for request path:{httpContext.Request.Path}, request method: {httpContext.Request.Method}");

            var statusCode = _codeMapper.Map(errors);
            var error = string.Join(",", errors.Select(x => x.Message));
            httpContext.Response.StatusCode = statusCode;
            // output error
            await httpContext.Response.WriteAsync(error);
        }
        else
        {
            Logger.LogDebug("no pipeline errors, setting and returning completed response");

            var downstreamResponse = httpContext.Items.DownstreamResponse();

            await _responder.SetResponseOnHttpContext(httpContext, downstreamResponse);
        }
    }
}

相比之前的中间件,主要变化就是对于 Error 的处理,感觉这里 ocelot 可以抽象一下,增加一个接口 ErrorResponser 之类的,现在的 responder 没有直接把错误信息直接传进去造成一些不变,加一个 ErrorResponder 只处理 Error 相关的逻辑,把错误信息直接传进去,这样用户也就可以更为灵活的注册自己的服务来无侵入的修改发生错误时的行为

Sample

要使用这个中间件,就要自己定义 ocelot 中间件的配置,把默认的 Response 中间件替换成自己的中间件即可,示例如下:

app.UseOcelot((ocelotBuilder, ocelotConfiguration) =>
{
    // this sets up the downstream context and gets the config
    app.UseDownstreamContextMiddleware();
    // This is registered to catch any global exceptions that are not handled
    // It also sets the Request Id if anything is set globally
    ocelotBuilder.UseExceptionHandlerMiddleware();

    // This is registered first so it can catch any errors and issue an appropriate response
    //ocelotBuilder.UseResponderMiddleware();
    ocelotBuilder.UseMiddleware<CustomResponseMiddleware>();

    ocelotBuilder.UseDownstreamRouteFinderMiddleware();
    ocelotBuilder.UseMultiplexingMiddleware();
    ocelotBuilder.UseDownstreamRequestInitialiser();
    ocelotBuilder.UseRequestIdMiddleware();

    // 自定义中间件,模拟没有权限的情况
    ocelotBuilder.Use((ctx, next) =>
    {
        ctx.Items.SetError(new UnauthorizedError("No permission"));
        return Task.CompletedTask;
    });
    //ocelotBuilder.UseMiddleware<UrlBasedAuthenticationMiddleware>();

    ocelotBuilder.UseLoadBalancingMiddleware();
    ocelotBuilder.UseDownstreamUrlCreatorMiddleware();
    ocelotBuilder.UseHttpRequesterMiddleware();
}).Wait();

除了上面的 Response 中间件,为了测试方便,我还加了一个中间件,直接设置了一个 Error 来方便测试,随便访问一个 Path 来测试一下是不是会有错误信息,可以看到正如预期的结果一样,输出了我们自定义的错误信息

More

完整示例可以从 Github 上获取 https://github.com/WeihanLi/AspNetCorePlayground/tree/master/OcelotDemo

Reference

标签:errors,自定义,中间件,错误信息,ocelotBuilder,ocelot,httpContext
来源: https://www.cnblogs.com/weihanli/p/14383810.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有