【问题标题】:Overwrite Response Body in Owin Middleware在 Owin 中间件中覆盖响应正文
【发布时间】:2019-09-12 06:12:30
【问题描述】:

我有一个正在使用的 Owin 中间件类。目的是在检测到 401、403 或 405 HTTP 状态代码时覆盖响应正文,并将正文替换为 JSON 对象。到目前为止,这是我的方法:

public override async Task Invoke(IOwinContext context)
        {
            await Next.Invoke(context);

            if (context.Response.StatusCode == 401 || context.Response.StatusCode == 403 || context.Response.StatusCode == 405)
            {

                var owinResponse = context.Response;
                var owinResponseStream = owinResponse.Body;
                var responseBuffer = new MemoryStream();
                owinResponse.Body = responseBuffer;

                string message;

                switch (context.Response.StatusCode)
                {
                    case 401:
                        message = "unauthorized request";
                        break;
                    case 403:
                        message = "forbidden request";
                        break;
                    default:
                        message = "request not allowed";
                        break;
                }
                var newResponse = new ResponseMessage<string>
                {
                    IsError = true,
                    StatusCode = (HttpStatusCode) Enum.Parse(typeof(HttpStatusCode), context.Response.StatusCode.ToString()),
                    Data = null,
                    Message = message
                };

                var customResponseBody = new StringContent(JsonConvert.SerializeObject(newResponse));
                var customResponseStream = await customResponseBody.ReadAsStreamAsync();
                await customResponseStream.CopyToAsync(owinResponseStream);
                owinResponse.ContentType = "application/json";
                owinResponse.ContentLength = customResponseStream.Length;
                owinResponse.StatusCode = 200;
                owinResponse.Body = owinResponseStream;
            }

        }

在大多数情况下它都在工作,但是响应正文被附加而不是替换。比如401错误的情况下,响应体是:

{"message":"Authorization has been denied for this request."}
{"IsError":true,"StatusCode":401,"Data":null,"Message":"unauthorized request"}

代替:

{"IsError":true,"StatusCode":401,"Data":null,"Message":"unauthorized request"}

我确定这与我写给响应正文的方式有关,但到目前为止还没有解决问题。

任何建议将不胜感激。

谢谢

【问题讨论】:

    标签: c# asp.net-web-api owin


    【解决方案1】:

    因为你在await Next.Invoke(context);之后写了下面的代码

    await Next.Invoke(context);
    
                if (context.Response.StatusCode == 401 || context.Response.StatusCode == 403 || context.Response.StatusCode == 405)
                {
    
                    var owinResponse = context.Response;
                    var owinResponseStream = owinResponse.Body;
                    var responseBuffer = new MemoryStream();
                    owinResponse.Body = responseBuffer;
    

    错了。

    下一个代码片段可以根据需要工作:

    public override async Task Invoke(IOwinContext context)
            {
                var owinResponse = context.Response;
                var owinResponseStream = owinResponse.Body;
                var responseBuffer = new MemoryStream();
                owinResponse.Body = responseBuffer;
    
                await Next.Invoke(context);
    
                if (context.Response.StatusCode == 401 || context.Response.StatusCode == 403 || context.Response.StatusCode == 405)
                {
    
                    string message;
    
                    switch (context.Response.StatusCode)
                    {
                        case 401:
                            message = "unauthorized request";
                            break;
                        case 403:
                            message = "forbidden request";
                            break;
                        default:
                            message = "request not allowed";
                            break;
                    }
                    var newResponse = new ResponseMessage<string>
                    {
                        IsError = true,
                        StatusCode = (HttpStatusCode) Enum.Parse(typeof(HttpStatusCode), context.Response.StatusCode.ToString()),
                        Data = null,
                        Message = message
                    };
    
                    var customResponseBody = new StringContent(JsonConvert.SerializeObject(newResponse));
                    var customResponseStream = await customResponseBody.ReadAsStreamAsync();
                    await customResponseStream.CopyToAsync(owinResponseStream);
                    owinResponse.ContentType = "application/json";
                    owinResponse.ContentLength = customResponseStream.Length;
                    owinResponse.StatusCode = 200;
                    owinResponse.Body = owinResponseStream;
                }
    
            }
    

    【讨论】:

      【解决方案2】:

      当您第一次将响应正文设置为内存流时,光标(当前位置)将移动到它的末尾。 owinResponse.Body = responseBuffer; ,结果,我们得到了{"message":"Authorization has been denied for this request."}stored 并且光标指向了末尾。

      同样,在方法结束时,您编写新的响应 owinResponse.Body = owinResponseStream;,其中包含消息 {"IsError":true,"StatusCode":401,"Data":null,"Message":"unauthorized request"}

      由于当前位置指向流的末尾,因此它会追加。

      尝试删除第一组正文owinResponse.Body = responseBuffer;,因为您不需要原始响应消息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多