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)是应用层的一种通信协议.它是一种请求/响应式的协议,即一个客户端与服务器建立连接后,向服务器发送一个请求;服务器接 ...
随机推荐
- jquery动态操作元素
<!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- C# HttpWebResponse下载限速
在使用HttpWebResponse请求网络内容的时候,一般如下面这种方法: code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // 非生产环境代码,请在实际使用时进行 ...
- WPF 鼠标在图片Image上悬停时切换更改设置图片源Source
// 无效的写法,图片不会被切换 <Image Margin="0,0,0,0" Width="50" Height="50" Sou ...
- ArcGIS for Desktop入门教程_第四章_入门案例分析 - ArcGIS知乎-新一代ArcGIS问答社区
原文:ArcGIS for Desktop入门教程_第四章_入门案例分析 - ArcGIS知乎-新一代ArcGIS问答社区 1 入门案例分析 在第一章里,我们已经对ArcGIS系列软件的体系结构有了一 ...
- 论文阅读计划1(Benchmarking Streaming Computation Engines: Storm, Flink and Spark Streaming & An Enforcement of Real Time Scheduling in Spark Streaming & StyleBank: An Explicit Representation for Neural Ima)
Benchmarking Streaming Computation Engines: Storm, Flink and Spark Streaming[1] 简介:雅虎发布的一份各种流处理引擎的基准 ...
- C++的 RTTI 观念和用途(非常详细)
自从1993年Bjarne Stroustrup [注1 ]提出有关C++ 的RTTI功能之建议﹐以及C++的异常处理(exception handling)需要RTTI:最近新推出的C++ 或多或少 ...
- SpringMVC与uploadify结合进行上传
uploadify是一个第三方js插件,支持多文件上传,拥有较为强大的上传功能 1.uploadify实现 下载其flash版本 http://www.uploadify.com/ 解压后将其内容区 ...
- Windows Phone 8加载外部动态链接库DLL(非安装包内的)
Windows Phone 8加载外部动态链接库DLL(非安装包内的) 在<动态加载与插件化>中大概介绍了下,wp8加载非安装包的下动态链接库,这次详细梳理下. 加载外部DLL主要的原理: ...
- python中的内置函数(bytearray)
返回一个新的字节数组.bytearray类是range 0 < = x < 256的一个可变序列.它有大多数可变序列的常用方法,在可变序列类型中描述,以及大多数字节类型的方法,参见字节和B ...
- flask相关使用
一.手动创建一个干净的含有蓝图的flask项目目录 在init.py中 from flask import Flaskmy_app=Flask(__name__)def create_app() ...