首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在日志记录中间件中返回自定义响应

在日志记录中间件中返回自定义响应
EN

Stack Overflow用户
提问于 2022-05-26 13:11:17
回答 1查看 141关注 0票数 0

我正在尝试制作日志记录中间件,它记录(请求、响应(在某些情况下是异常),当异常发生时,我想返回自定义响应。

当前,当出现异常时,我无法写入响应体。

我的代码:

代码语言:javascript
运行
复制
public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            context.Request.EnableBuffering();
            using (var reader = new StreamReader(
                context.Request.Body,
                encoding: Encoding.UTF8,
                detectEncodingFromByteOrderMarks: false,
                bufferSize: 1024,
                leaveOpen: true))
            {
                strRequestBody = await reader.ReadToEndAsync();
                context.Request.Body.Position = 0;
            }

            var originalResponseBody = context.Response.Body;
            using var newResponseBody = new MemoryStream();
            context.Response.Body = newResponseBody;

            await _next(context);

            if (context.Response.StatusCode != 200)
            {
                newResponseBody.Seek(0, SeekOrigin.Begin);
                var jsonResponseBody = JObject.Parse(await new StreamReader(context.Response.Body).ReadToEndAsync());
                newResponseBody.Seek(0, SeekOrigin.Begin);
                await newResponseBody.CopyToAsync(originalResponseBody);

                _logger.LogInformation(
                    "HTTP {method} {url} => responded {statusCode}\n" +
                    "(response code: {responseCode}, response message: {message})\n" +
                    "Request query string: {queryString} \n" +
                    "Request body: {requestBody}",
                    context.Request?.Method,
                    context.Request?.Path.Value,
                    context.Response?.StatusCode,
                    jsonResponseBody["code"].ToString(),
                    jsonResponseBody["message"].ToString(),
                    context.Request?.QueryString.Value,
                    strRequestBody);
            }
            else
            {
                _logger.LogInformation(
                    "HTTP {method} {url} => responded {statusCode} \n" +
                    "Request query string: {queryString} \n" +
                    "Request body: {requestBody}",
                    context.Request?.Method,
                    context.Request?.Path.Value,
                    context.Response?.StatusCode,
                    context.Request?.QueryString.Value,
                    strRequestBody);
            }

        }
        catch (Exception ex)
        {
            context.Response.StatusCode = 500;
            context.Response.ContentType = "application/json";
            string jsonResponse = JsonConvert.SerializeObject(
                BaseResponse.Failed(500, "Somthing went wrong."));
            await context.Response.WriteAsync(jsonResponse, Encoding.UTF8);

            _logger.LogError(
                    "HTTP {method} {url} => responded {statusCode} \n" +
                    "Request query string: {queryString} \n" +
                    "Request body: {requestBody} \n" +
                    "Error: {error}",
                    context.Request?.Method,
                    context.Request?.Path.Value,
                    context.Response?.StatusCode,
                    context.Request?.QueryString.Value,
                    strRequestBody,
                    "Exception message: " + ex.Message + "\n" +
                    "Exception stacktrace: " + ex.StackTrace + "\n" +
                    "Inner exception message: " + ex.InnerException?.Message + "\n" +
                    "Inner exception stacktrace: " + ex.InnerException?.StackTrace);
        }
    }

在(catch)块中,这一行:

代码语言:javascript
运行
复制
await context.Response.WriteAsync(jsonResponse, Encoding.UTF8);

抛出此异常:

代码语言:javascript
运行
复制
System.ObjectDisposedException: Cannot access a closed Stream.

我的问题:在发生异常时,如何从中间件返回自定义响应?

提前谢谢,

EN

回答 1

Stack Overflow用户

发布于 2022-05-26 23:43:21

响应体是不可读的流,因此您需要将一个可读流分配给主体,以便读取它,如下行:

代码语言:javascript
运行
复制
var originalResponseBody = context.Response.Body;
using var newResponseBody = new MemoryStream();
context.Response.Body = newResponseBody;

在MemoryStream等待_next(上下文)之前,我们将它分配给响应体。

等待_next(上下文)被调用并且管道中发生异常时,执行转到(catch)块,这里我们需要将响应体还原回原来的流,然后在(catch)块(第一行)中写入它:

代码语言:javascript
运行
复制
catch (Exception ex)
        {
            context.Response.Body = originalResponseBody;
            context.Response.StatusCode = 500;
            context.Response.ContentType = "application/json";
            string jsonResponse = JsonConvert.SerializeObject(
                BaseResponse.Failed(500, "Somthing went wrong."));
            await context.Response.WriteAsync(jsonResponse, Encoding.UTF8);

            _logger.LogError(
                    "HTTP {method} {url} => responded {statusCode} \n" +
                    "Request query string: {queryString} \n" +
                    "Request body: {requestBody} \n" +
                    "Error: {error}",
                    context.Request?.Method,
                    context.Request?.Path.Value,
                    context.Response?.StatusCode,
                    context.Request?.QueryString.Value,
                    strRequestBody,
                    "Exception message: " + ex.Message + "\n" +
                    "Exception stacktrace: " + ex.StackTrace + "\n" +
                    "Inner exception message: " + ex.InnerException?.Message + "\n" +
                    "Inner exception stacktrace: " + ex.InnerException?.StackTrace);
        }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72392385

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档