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;
}
}
}
NetCore 中间件获取请求报文和返回报文的更多相关文章
- spring-boot 使用Aop通知打印控制器请求报文和返回报文
一.简介 开发过程中我们往往需要写许多例如: @GetMapping("/id/get") public Result getById( String id) throws Exc ...
- .net core webapi通过中间件获取请求和响应内容
本文主要根据中间件来实现对.net core webapi中产生的请求和响应数据进行获取并存入日志文件中: 这里不详细介绍日志文件的使用.你可以自己接入NLog,log4net,Exceptionle ...
- 切面(Aspect)获取请求参数和返回值
@Before("webLog()") public void doBefore(JoinPoint joinPoint) throws Throwable { // 接收到请求, ...
- django中间件(获取请求ip)
def simple_middleware(get_response): # 此处编写的代码仅在Django第一次配置和初始化的时候执行一次. print('1----django启动了') def ...
- HTTP的请求报文与响应报文
报文: 简单来说,报文就是也就是HTTP报文,作用是在各个系统之间进行和响应时用来交换与传输的数据单元,即站点一次性要发送的数据块,这些数据块以一些文本形式的元信息开头,这些信息描述了报文的内容及含义 ...
- 调用中行接口针对返回报文(xml形式)做相关处理
最近在对接中行银行接口,在获取返回报文的时候遇到一些问题,现在在这里做个总结 TIP: 在返回报文之前,要对前置机的URL请求,在这期间遇到一个坑,还是通过查看日志才发现问题 在填写转账信息的时候要求 ...
- HTTP请求报文、响应报文
HTTP请求报文 HTTP请求报文由3部分组成(请求行+请求头+请求体): 请求行:①是请求方法,GET和POST是最常见的HTTP方法,除此以外还包括DELETE.HEAD.OPTIONS.PUT. ...
- 重温Http协议--请求报文和响应报文
http协议是位于应用层的协议,我们在日常浏览网页比如在导航网站请求百度首页的时候,会先通过http协议把请求做一个类似于编码的工作,发送给百度的服务器,然后在百度服务器响应请求时把相应的内容再通过h ...
- 关于HTTP请求报文和响应报文学习笔记
超文本传输协议(Hypertext Transfer Protocol,简称HTTP)是应用层的一种通信协议.它是一种请求/响应式的协议,即一个客户端与服务器建立连接后,向服务器发送一个请求;服务器接 ...
随机推荐
- Installshield 在安装或者卸载过程中,判断某一程序是否正在运行
1.在操作时,首先引入类库ShutDownRunningApp.rul,其中ShutDownRunningApp.rul代码如下 /////////////////////////////////// ...
- swagger-editor
前言 上一篇文章我们有提到Swagger做接口的定义是采用yaml语言的,当然,yaml是个啥,大家自行百度.阿福在此不做赘述了.但是,今天我们要来讲的是yaml支持比较好的Swagger-Edito ...
- List遍历删除 或取指定的前N项
class Program { static void Main(string[] args) { /* * List遍历删除 或取指定的前N项 */ List<PerSon> listP ...
- 笔记:认识.NET平台
认识.NET平台先了解一堆技术术语和缩写 http://www.cnblogs.com/dbycl/p/6419456.html 天生不跨平台的.NET Framework 2.大家都来开发新语言 3 ...
- SimpleMembership,成员资格提供程序、 通用的提供者和新的 ASP.NET 4.5 Web 窗体和 ASP.NET MVC 4 模板
ASP.NET MVC 4 互联网模板中添加一些新的. 非常有用的功能,构建 SimpleMembership.这些更改将添加一些很有特色,像很多更简单. 可扩展会员 API 和 OAuth 的支持. ...
- 动态链接库(Dynamic Link Library)学习笔记(附PE文件分析)
转载:http://www.cnblogs.com/yxin1322/archive/2008/03/08/donamiclinklibrary.html 作者:EricYou 转载请注明出处 注 ...
- Windows下获取高精度时间注意事项 [转贴 AdamWu]
花了很长时间才得到的经验,与大家分享. 1. RDTSC - 粒度: 纳秒级 不推荐优势: 几乎是能够获得最细粒度的计数器抛弃理由: A) 定义模糊 - 曾经据说是处理器的cycle counter, ...
- 使用mingw编译完整Qt5的过程(使用了niXman的msys套装)good
使用mingw编译完整Qt5的过程 坛子里似乎已经有人编译出Qt5了,不过大多有问题,不是缺少opengl就是缺少openssl,还有缺少webkit的,本文提供的仍然不能说是绝对完整的,不过相对以前 ...
- 我整理的一份来自于线上的Nginx配置(Nginx.conf),希望对学习Nginx的有帮助
我整理了一份Nginx的配置文件说明,是真正经历过正式线上考验过.如果有优化的地方,也请朋友们指点一二,整理出一份比较全而实用的配置. 主要包含配置:负载均衡配置,页面重定向,转发,HTTPS和HTT ...
- gitlab安装笔记二_Centos7配置163yum源
进入配置目录 cd /etc/yum.repos.d 压缩备份原有的配置 sudo tar cvf base.tar.gz *.repo 可以解压查看备份 sudo tar xvf base. ...