简体   繁体   English

在Owin中间件中覆盖响应主体

[英]Overwrite Response Body in Owin Middleware

I have an Owin middleware class that I'm using. 我有一个我正在使用的Owin中间件类。 The purpose is to overwrite the response body when a 401, 403, or 405 HTTP status code is detected and replace the body with a JSON object. 目的是在检测到401,403或405 HTTP状态代码时覆盖响应正文,并用JSON对象替换正文。 This is my method so far: 到目前为止这是我的方法:

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;
            }

        }

For the most part it is working, however the response body is being appended to instead of replaced. 在大多数情况下它是有效的,但是响应主体被附加到而不是被替换。 For example, in the case of a 401 error, the response body is: 例如,在401错误的情况下,响应正文是:

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

instead of: 代替:

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

I'm sure that it has something to do with the way I'm writing to the response body but nothing so far has resolved the issue. 我确信这与我写回响应机构的方式有关,但到目前为止还没有解决问题。

Any suggestions would be greatly appreciated. 任何建议将不胜感激。

Thank You 谢谢

When you first set the response body to the memory stream, the cursor(current position ) would move to the end of it. 当您首先将响应主体设置为内存流时,光标(当前位置)将移动到它的末尾。 owinResponse.Body = responseBuffer; , as a result, we got {"message":"Authorization has been denied for this request."} stored and the cursor points at the end. 结果,我们得到{"message":"Authorization has been denied for this request."}存储,光标指向最后。

Again, at the end of your method, you write the new response owinResponse.Body = owinResponseStream; 再次,在您的方法结束时,您编写新的响应owinResponse.Body = owinResponseStream; which has the message {"IsError":true,"StatusCode":401,"Data":null,"Message":"unauthorized request"} 其中包含消息{"IsError":true,"StatusCode":401,"Data":null,"Message":"unauthorized request"}

Since the current position is pointing at the end of the stream, therefore it will append. 由于当前位置指向流的末尾,因此它将附加。

Try to remove the first set of the body owinResponse.Body = responseBuffer; 尝试删除第一组body owinResponse.Body = responseBuffer; as you don't need the original response message. 因为您不需要原始响应消息。

Because you write below code after await Next.Invoke(context); 因为你在await Next.Invoke(context);之后写下面的代码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;

Its wrong. 这是不对的。

Next code snipet work as you want: 下一代码snipet可以随意工作:

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;
            }

        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM