- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有 .net 核心 WEB API 应用程序 MassTransit (用于实现 RabbitMQ 消息代理)。 RabbitMQ-MassTransit 配置很简单,只需在 Startup.cs
文件中用几行代码即可完成。
services.AddMassTransit(x =>
{
x.AddConsumer<CustomLogConsume>();
x.AddBus(provider => Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = cfg.Host(new Uri("rabbitmq://rabbitmq/"), h =>
{
h.Username("guest");
h.Password("guest");
});
cfg.ExchangeType = ExchangeType.Fanout;
cfg.ReceiveEndpoint(host, "ActionLog_Queue", e =>
{
e.PrefetchCount = 16;
});
// or, configure the endpoints by convention
cfg.ConfigureEndpoints(provider);
}));
});
我在我的项目解决方案中使用依赖注入(inject)以获得更好的代码标准。发布消息适用于 Controller 依赖注入(inject)。但是当我实现自定义 middle ware 时对于日志操作,Masstransit 未能正确发布消息,它在 RabbitMQ Web 控制台中创建了一个带有 _error
的额外队列。
public class RequestResponseLoggingMiddleware
{
#region Private Variables
/// <summary>
/// RequestDelegate
/// </summary>
private readonly RequestDelegate _next;
/// <summary>
/// IActionLogPublish
/// </summary>
private readonly IActionLogPublish _logPublish;
#endregion
#region Constructor
public RequestResponseLoggingMiddleware(RequestDelegate next, IActionLogPublish logPublish)
{
_next = next;
_logPublish = logPublish;
}
#endregion
#region PrivateMethods
#region FormatRequest
/// <summary>
/// FormatRequest
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private async Task<ActionLog> FormatRequest(HttpRequest request)
{
ActionLog actionLog = new ActionLog();
var body = request.Body;
request.EnableRewind();
var context = request.HttpContext;
var buffer = new byte[Convert.ToInt32(request.ContentLength)];
await request.Body.ReadAsync(buffer, 0, buffer.Length);
var bodyAsText = Encoding.UTF8.GetString(buffer);
request.Body = body;
var injectedRequestStream = new MemoryStream();
var requestLog = $"REQUEST HttpMethod: {context.Request.Method}, Path: {context.Request.Path}";
using (var bodyReader = new StreamReader(context.Request.Body))
{
bodyAsText = bodyReader.ReadToEnd();
if (string.IsNullOrWhiteSpace(bodyAsText) == false)
{
requestLog += $", Body : {bodyAsText}";
}
var bytesToWrite = Encoding.UTF8.GetBytes(bodyAsText);
injectedRequestStream.Write(bytesToWrite, 0, bytesToWrite.Length);
injectedRequestStream.Seek(0, SeekOrigin.Begin);
context.Request.Body = injectedRequestStream;
}
actionLog.Request = $"{bodyAsText}";
actionLog.RequestURL = $"{request.Scheme} {request.Host}{request.Path} {request.QueryString}";
return actionLog;
}
#endregion
#region FormatResponse
private async Task<string> FormatResponse(HttpResponse response)
{
response.Body.Seek(0, SeekOrigin.Begin);
var text = await new StreamReader(response.Body).ReadToEndAsync();
response.Body.Seek(0, SeekOrigin.Begin);
return $"Response {text}";
}
#endregion
#endregion
#region PublicMethods
#region Invoke
/// <summary>
/// Invoke - Hits before executing any action. Actions call executes from _next(context)
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task Invoke(HttpContext context)
{
ActionLog actionLog = new ActionLog();
actionLog = await FormatRequest(context.Request);
var originalBodyStream = context.Response.Body;
using (var responseBody = new MemoryStream())
{
context.Response.Body = responseBody;
await _next(context);
actionLog.Response = await FormatResponse(context.Response);
await _logPublish.Publish(actionLog);
await responseBody.CopyToAsync(originalBodyStream);
}
}
#endregion
#endregion
}
启动时配置中间件
public async void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime)
{
............
app.UseMiddleware<RequestResponseLoggingMiddleware>();
....................
}
MassTransit 在启动时是否有任何额外的配置来与中间件一起工作
编辑
IActionLogPublish
public interface IActionLogPublish
{
Task Publish(ActionLog model);
}
ActionLogPublish
public class ActionLogPublish : IActionLogPublish
{
private readonly IBus _bus;
public ActionLogPublish(IBus bus)
{
_bus = bus;
}
public async Task Publish(ActionLog actionLogData)
{
/* Publish values to RabbitMQ Service Bus */
await _bus.Publish(actionLogData);
/* Publish values to RabbitMQ Service Bus */
}
}
编辑
RabbitMQ 网络控制台
最佳答案
中间件需要将原始主体放回响应中。
注入(inject)的依赖项也适用于 Controller 而不是中间件,因为它可能在作用域生命周期内注册。
在那种情况下,它不应该被构造函数注入(inject)到 middlewre 中,而是直接注入(inject)到 Invoke
Because middleware is constructed at app startup, not per-request, scoped lifetime services used by middleware constructors aren't shared with other dependency-injected types during each request. If you must share a scoped service between your middleware and other types, add these services to the
Invoke
method's signature. TheInvoke
method can accept additional parameters that are populated by DI:
//...omitted for brevity
public RequestResponseLoggingMiddleware(RequestDelegate next) {
_next = next;
}
//...
private async Task<string> FormatResponseStream(Stream stream) {
stream.Seek(0, SeekOrigin.Begin);
var text = await new StreamReader(stream).ReadToEndAsync();
stream.Seek(0, SeekOrigin.Begin);
return $"Response {text}";
}
public async Task Invoke(HttpContext context, IActionLogPublish logger) {
ActionLog actionLog = await FormatRequest(context.Request);
//keep local copy of response stream
var originalBodyStream = context.Response.Body;
using (var responseBody = new MemoryStream()) {
//replace stream for down stream calls
context.Response.Body = responseBody;
await _next(context);
//put original stream back in the response object
context.Response.Body = originalBodyStream; // <-- THIS IS IMPORTANT
//Copy local stream to original stream
responseBody.Position = 0;
await responseBody.CopyToAsync(originalBodyStream);
//custom logging
actionLog.Response = await FormatResponse(responseBody);
await logger.Publish(actionLog);
}
}
When using a scoped service in a middleware, inject the service into the
Invoke
orInvokeAsync
method. Don't inject via constructor injection because it forces the service to behave like a singleton. For more information, see Write custom ASP.NET Core middleware.
强调我的
关于c# - 带有 Masstransit 发布的中间件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58297986/
有人可以给我一个更简单的以下代码的解决方案(它正在展开给定结构 0xFC :: len :: payload :: ... :: 0x0A :: 0x0D 的整数列表): object Payload
我已经在我的网站上安装了 SSL 证书,但 intermediate.crt 无法正常工作。任何 SSL 检查器(例如 GeoTrust Checker)都告诉我,缺少中间 key 。网站上已经使用了
如何让图像从这个框的中间开始? (中间纵横) 最佳答案 有几种方法可以做到这一点,如果它需要在所有浏览器(IE7+ 和其他浏览器)中工作,你需要做不同的事情来让它在某些情况下工作。 使用绝对位置
如何强制 min-height 和 vertical-align:middle 为 td 元素或其内部元素工作? 最佳答案 td 元素上的 height 等同于 min-height,因为如果需要,表
我正在尝试自动滚动到订单簿的中间行。 我有 orderBook div,其中放置了带有 orderBook 的表。该表的其中一行有一个 id middleRow。我想做的是滚动该行并将其放置在 ord
我正在尝试在 javascript 中计算绝对定位元素的 transform-origin 属性,以便它们在悬停时填充整个视口(viewport)。 我尝试通过 x 除以窗口宽度和 y 除以窗口高度来
我有休闲字符串 ' this is my string ' 是否可以删除开头和结尾的所有空格,只在单词之间留一个空格。 要选择我使用过的所有空间: SELECT regexp_replace('
我正在设法创建我的第一个复杂的 J2E 解决方案,并且在每个教程中我都发现了某种中间表的用法,如下所示: 表:用户、用户角色、角色虽然逻辑会简单地向用户表添加一个键来引用它在角色表上的角色,但为什么要
我正在寻找以下解决方案。我想定位一个图像元素,例如 在中间。所以高度是视口(viewport)的高度,宽度会自动设置,图像的中间应该在视口(viewport)宽度的中间。 我搜索的一个例子就像下面的网
我正在设计一种布局,它更像是注册用户的个人仪表板。我让它变得简单,使用基本的 2 列网格,一个用于侧边栏,一个用于主要内容。 因为,例如,80% 的网站使用将发生在一个单独的子系统中,在无 chrom
我有三个不同的 div 标签(不在彼此内部)和代码,所以它有一个把单词放在左边、中间或右边,但中心非常偏离中心。这是 HTML 代码: .desc { float: right; color:
我有以下CSS http://jsbin.com/azivip/75/edit我想让黄色的 div 高度填充蓝色和绿色 div 之间的空间。使用高度继承似乎使 div 超出了绿色 div。 有什么想法
我不得不在其父元素的中间放置一些文本。我用下面的代码实现了它: #div1 { position: relative; margin: 0; padding: 0; } #div2 {
发现一个使用合法证书(由thawte 签名)的网站,但所有浏览器都会拒绝它。我不明白为什么。thawte 的支持告诉我一个域有两个证书,然后将这个 https://www.sslshopper[dot
我正在尝试使用 OpenSSL 创建证书链,但出于某种原因,当我在我的计算机上安装我的根 CA 并尝试验证证书链时,它总是告诉我它找不到证书的颁发者.为了让事情发生,我必须安装中间 CA,这是没有意义
我看到 REST 的一大好处是依赖 HTTP 缓存。我不是在争论这个,而是完全认同这个想法。但是,我从来没有看到对中间 HTTP 缓存的更深入的解释。 如果我将 Cache-control heade
查看此图片 Facebook Messenger Android App Buttons ( MESSENGER\ACTIVE ) 我怎样才能做到这一点? 详细信息:- 带有 2px 红色边框的 di
我的任务是制作漂亮的文本,在文本中间加一条白线,如下图所示。是否可以使用 css 来实现?这是 Fiddle .container{ height:200px; width:400px;
在拉丁文字中,字母有大写和小写形式。在 Python 中,如果你想比较两个字符串而不考虑它们的大小写,你可以使用 'string'.upper() 或 'string'.lower() 将它们转换为相
我正在使用 awk 对文件进行一些文本处理。例如删除尾随空格。 awk '{gsub(/ +$/, "")} {print $0}' filename 这很好用。但是当我将输出重定向到原始文件时。它变
我是一名优秀的程序员,十分优秀!