在异常期间捕获原始 HTTP POST 数据
Posted
技术标签:
【中文标题】在异常期间捕获原始 HTTP POST 数据【英文标题】:Capturing raw HTTP POST Data during Exception 【发布时间】:2010-10-28 18:03:47 【问题描述】:我有一个托管在 IIS/ASP.NET 中的 WCF 服务,它接受序列化对象的 HTTP 发布(不是表单发布)。
如果客户端发送格式错误的请求(例如,它们没有正确序列化对象),我想记录发送的消息。
我们已经在使用 ELMAH 来捕获未处理的异常,因此简单地附加发布数据将是最简单的选择。
我可以在异常期间获取当前的 HttpContext,但这仅包含 HTTP 标头信息。
我的问题是:有什么方法可以捕获原始的 HTTP POST 请求正文吗?或者,失败了 - 捕获导致错误的输入的更好方法(没有反向代理)?
编辑:澄清一下,始终运行数据包级捕获并不适合。我正在寻找一个可以部署到生产服务器的解决方案,该解决方案将使客户端超出我们的控制或监控能力。
编辑#2:建议访问 Request.InputStream - 如果您在 WCF 从流中读取请求后尝试读取,这将不起作用。
这里有一段代码示例,可以查看我是如何尝试使用它的。
StringBuilder log = new StringBuilder();
var request = HttpContext.Current.Request;
if (request.InputStream != null)
log.AppendLine(string.Format("request.InputStream.Position = \"0\"", request.InputStream.Position));
if (request.InputStream.Position != 0)
request.InputStream.Seek(0, System.IO.SeekOrigin.Begin);
using (StreamReader sr = new StreamReader(request.InputStream))
log.AppendLine(string.Format("Original Input: \"0\"", sr.ReadToEnd()));
else
log.AppendLine("request.Inputstream = null");
log.ToString();
log.ToString() 的输出是:
request.InputStream.Position = "0" 原始输入:“”【问题讨论】:
StreamReader 的“使用”将导致 System.Web.Request.InputStream 被释放(这意味着数据丢失)。 【参考方案1】:当它到达您的服务时,请求已被处理,您无法使用。
但是...您可以附加message inspector。消息检查器允许您在消息到达您的操作实现之前对其进行处理。您可以创建消息的缓冲副本,并将其复制到 OperationContext.Current。
当然是丑陋的 hack,这意味着内存开销,因为现在每个请求都有两个消息副本浮动。
【讨论】:
谢谢 - 这不是一个特别好的解决方案,但牺牲一些内存可能是值得的。【参考方案2】:您是否查看了 System.Web.Request.InputStream 属性?它应该有你想要的。
如何“倒回” InputStream 属性。
if (Request.InputStream.Position != 0)
Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin);
您应该考虑的另一个选项是在 BeginRequest 事件上使用 HTTPModule 捕获此信息。数据应该在 BeginRequest 事件中存在,因为我不相信 WCF 会在 PostAuthenticateEvent 之后接收请求。
【讨论】:
我确实看过该属性 - 不幸的是,该流仅包含未读数据。到异常发生时,WCF 已经读取了输入数据。您不能倒带/重置位置。 查看我的更新...由于 Request.InputStream.CanSeek 为真,您可以使用 Seek 方法将位置重置回 0。 感谢您的更新 - CanSeek 是正确的,但是流中仍然没有任何内容可供读取。请参阅更新的文本,了解我为尝试和测试所做的工作。【参考方案3】:在 ASP.NET(IIS 下的 ASP Web 服务)下,以下代码有帮助:
if (request.InputStream.Position != 0)
request.InputStream.Seek(0, System.IO.SeekOrigin.Begin);
WCF 可能不同(即在读取后 Dispose InputStream)
【讨论】:
这与杰夫给出的答案相同。它也不起作用,因为流不可搜索。【参考方案4】:使用提琴手。免于 MS。效果很好。
【讨论】:
我说的是当没有 Fiddler、Wireshark 或其他任何运行来捕获它时发生的错误。例如,在无法一直运行数据包捕获的生产或登台服务器上。以上是关于在异常期间捕获原始 HTTP POST 数据的主要内容,如果未能解决你的问题,请参考以下文章
CoreData:错误:严重的应用程序错误。在核心数据更改处理期间捕获到异常
CoreData:错误:严重的应用程序错误。在核心数据更改处理期间捕获到异常
Swift CoreData:错误:严重的应用程序错误。在核心数据更改处理期间捕获到异常。