NetCore 中间件获取请求报文和返回报文

  

using System;
using System.IO;

namespace WebApi.Restful.Middlewares
{
    public class MemoryWrappedHttpResponseStream : MemoryStream
    {
        private Stream _innerStream;
        public MemoryWrappedHttpResponseStream(Stream innerStream)
        {
            this._innerStream = innerStream ?? throw new ArgumentNullException(nameof(innerStream));
        }
        public override void Flush()
        {
            this._innerStream.Flush();
            base.Flush();
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            base.Write(buffer, offset, count);
            this._innerStream.Write(buffer, offset, count);
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            if (disposing)
            {
                this._innerStream.Dispose();
            }
        }

        public override void Close()
        {
            base.Close();
            this._innerStream.Close();
        }
    }
}

    

using Exceptionless;
using gateway.api;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace WebApi.Restful.Middlewares
{

/// <summary> /// 请求日志记录中间件 /// </summary> public class RequestLoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; public RequestLoggingMiddleware(RequestDelegate next, ILogger<RequestLoggingMiddleware> logger) { _next = next; _logger = logger; } public async Task Invoke(HttpContext context) { context.TraceIdentifier = Guid.NewGuid().ToString("N"); var request = context.Request; await RequestEnableRewindAsync(request).ConfigureAwait(false); var encoding = GetRequestEncoding(request); var requestContent = await ReadStreamAsync(request.Body, encoding).ConfigureAwait(false); WritLog(context, JsonConvert.SerializeObject(requestContent)); await ResponseEnableRewindAsync(context.Response); context.Response.OnCompleted(ResponseCompletedCallback, context); await _next(context); } private async Task ResponseCompletedCallback(object obj) { if (obj is HttpContext context) { var response = await ResponseReadStreamAsync(context.Response);
         //记录日志 //ExceptionlessClient.Default.CreateLog(JsonConvert.SerializeObject(response)).AddTags(context.TraceIdentifier).Submit(); } } private async Task<string> ResponseReadStreamAsync(HttpResponse response) { if (response.Body.Length > 0) { response.Body.Seek(0, SeekOrigin.Begin); var encoding = GetEncoding(response.ContentType); var retStr = await ReadStreamAsync(response.Body, encoding, false).ConfigureAwait(false); return retStr; } return null; } private async Task<string> ReadStreamAsync(Stream stream, Encoding encoding, bool forceSeekBeginZero = true) { using (StreamReader sr = new StreamReader(stream, encoding, true, 1024, true))//这里注意Body部分不能随StreamReader一起释放 { var str = await sr.ReadToEndAsync(); if (forceSeekBeginZero) { stream.Seek(0, SeekOrigin.Begin);//内容读取完成后需要将当前位置初始化,否则后面的InputFormatter会无法读取 } return str; } } private void WritLog(HttpContext context, string body) { var request = context.Request; try { Task.Factory.StartNew(() => { LogMode logMode = new LogMode { Body = body, CententLength = request.ContentLength, CententType = request.ContentType, Headers = JsonConvert.SerializeObject(request.Headers), Host = request.Host.Host, Method = request.Method, Path = request.Path, Query = JsonConvert.SerializeObject(request.Query) };
           // 记录日志 // ExceptionlessClient.Default.CreateLog(JsonConvert.SerializeObject(logMode)).AddTags(context.TraceIdentifier).Submit(); }); } catch (Exception ex) {
          //记录日志 //ex.ToExceptionless().Submit(); } } private async Task ResponseEnableRewindAsync(HttpResponse response) { if (!response.Body.CanRead || !response.Body.CanSeek) { response.Body = new MemoryWrappedHttpResponseStream(response.Body); } } private async Task RequestEnableRewindAsync(HttpRequest request) { if (!request.Body.CanSeek) { request.EnableBuffering(); await request.Body.DrainAsync(CancellationToken.None); request.Body.Seek(0L, SeekOrigin.Begin); } } private async Task<string> ReadStreamAsync(Stream stream, Encoding encoding) { using (StreamReader sr = new StreamReader(stream, encoding, true, 1024, true))//这里注意Body部分不能随StreamReader一起释放 { var str = await sr.ReadToEndAsync(); stream.Seek(0, SeekOrigin.Begin);//内容读取完成后需要将当前位置初始化,否则后面的InputFormatter会无法读取 return str; } } private Encoding GetRequestEncoding(HttpRequest request) { var requestContentType = request.ContentType; var requestMediaType = requestContentType == null ? default(MediaType) : new MediaType(requestContentType); var requestEncoding = requestMediaType.Encoding; if (requestEncoding == null) { requestEncoding = Encoding.UTF8; } return requestEncoding; } private Encoding GetEncoding(string contentType) { var mediaType = contentType == null ? default(MediaType) : new MediaType(contentType); var encoding = mediaType.Encoding; if (encoding == null) { encoding = Encoding.UTF8; } return encoding; } public class LogMode { public string Body { get; set; } public long? CententLength { get; set; } public string CententType { get; set; } public string Headers { get; set; } public string Host { get; set; } public string Method { get; set; } public string Path { get; set; } public string Query { get; set; } } private Dictionary<string, IEnumerable<string>> GetHeaders(HttpRequestMessage request) { var result = new Dictionary<string, IEnumerable<string>>(); foreach (var pair in request.Headers) { result.Add(pair.Key, pair.Value); } return result; } } }  

转载于:https://www.cnblogs.com/sunqiang/p/10174972.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值