博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NetCore 中间件获取请求报文和返回报文
阅读量:4521 次
发布时间:2019-06-08

本文共 7442 字,大约阅读时间需要 24 分钟。

  

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{
/// /// 请求日志记录中间件 /// public class RequestLoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; public RequestLoggingMiddleware(RequestDelegate next, ILogger
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
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
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
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
> GetHeaders(HttpRequestMessage request) { var result = new Dictionary
>(); foreach (var pair in request.Headers) { result.Add(pair.Key, pair.Value); } return result; } }}  

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

你可能感兴趣的文章
Linux常用命令
查看>>
AutoFac IoC DI 依赖注入
查看>>
.net中的设计模式---单例模式
查看>>
安装程序工具 (Installutil.exe)22
查看>>
python 学习(pip工具的安装)
查看>>
博客园在我的博客添加点击小心心特效
查看>>
如何简单解释 MapReduce算法
查看>>
微软Office Online服务安装部署(二)
查看>>
从 0 到 1 实现 React 系列 —— 1.JSX 和 Virtual DOM
查看>>
面向接口编程详解(二)——编程实例
查看>>
解决java.lang.NoClassDefFoundError: org/apache/log4j/Level
查看>>
端口号
查看>>
mysql for macOS安装
查看>>
iOS中的KeyChain的用途
查看>>
jquery与checkbox的checked属性的问题
查看>>
HDU5092——Seam Carving(动态规划+回溯)(2014上海邀请赛重现)
查看>>
java 格式化字符串
查看>>
[.Net]轻量ORM——Dapper
查看>>
语言基础
查看>>
C# : 操作Word文件的API - (将C# source中的xml注释转换成word文档)
查看>>