在 ASP.NET MVC 中记录原始 HTTP 请求/响应 IIS7
我正在编写一个 Web 服务(使用 ASP.NET MVC),出于支持目的,我们希望能够以尽可能接近原始的在线格式(即包括 HTTP方法、路径、所有标头和正文)存入数据库。
我不确定如何以最少“损坏”的方式获取这些数据。 我可以通过检查 HttpRequest 对象的所有属性并从中构建一个字符串(对于响应也类似)来重新构建我认为请求的样子,但我真的很想掌握通过线路发送的实际请求/响应数据。
我很乐意使用任何拦截机制,例如过滤器、模块等,并且该解决方案可以特定于 IIS7。 但是,我更愿意仅将其保留在托管代码中。
有什么建议吗?
编辑:我注意到HttpRequest
有一个SaveAs
方法,可以将请求保存到磁盘,但这会使用无法公开访问的内部辅助方法负载从内部状态重建请求(我不知道为什么这不允许保存到用户提供的流)。 所以看起来我必须尽力从对象中重建请求/响应文本......呻吟。
编辑2:请注意,我说的是整个请求,包括方法、路径、标头等。当前响应仅查看不包含此信息的正文流。
编辑3:没有人阅读这里的问题吗? 到目前为止有五个答案,但没有一个甚至暗示一种获取整个原始在线请求的方法。 是的,我知道我可以捕获输出流、标头、URL 以及请求对象中的所有内容。 我已经在问题中说过了,请参阅:
我可以通过检查 HttpRequest 对象的所有属性并从中构建一个字符串(对于响应也类似)来重新构建我认为请求的样子,但我真的很想掌握实际的请求/通过线路发送的响应数据。
如果您知道无法检索完整原始数据(包括标头、url、http 方法等),那么了解这一点将会很有用。 同样,如果您知道如何以原始格式获取所有内容(是的,我的意思仍然是包括标头、url、http 方法等),而无需重建它(这就是我所要求的),那么这将非常有用。 但是告诉我可以从 HttpRequest
/HttpResponse
对象重建它是没有用的。 我知道。 我已经说过了。
请注意:在有人开始说这是一个坏主意,或者会限制可扩展性等之前,我们还将在分布式环境中实现节流、顺序交付和反重放机制,因此需要数据库日志记录反正。 我并不是在寻求讨论这是否是一个好主意,而是在寻找如何实现它。
I'm writing a web service (using ASP.NET MVC) and for support purposes we'd like to be able to log the requests and response in as close as possible to the raw, on-the-wire format (i.e including HTTP method, path, all headers, and the body) into a database.
What I'm not sure of is how to get hold of this data in the least 'mangled' way. I can re-constitute what I believe the request looks like by inspecting all the properties of the HttpRequest
object and building a string from them (and similarly for the response) but I'd really like to get hold of the actual request/response data that's sent on the wire.
I'm happy to use any interception mechanism such as filters, modules, etc. and the solution can be specific to IIS7. However, I'd prefer to keep it in managed code only.
Any recommendations?
Edit: I note that HttpRequest
has a SaveAs
method which can save the request to disk but this reconstructs the request from the internal state using a load of internal helper methods that cannot be accessed publicly (quite why this doesn't allow saving to a user-provided stream I don't know). So it's starting to look like I'll have to do my best to reconstruct the request/response text from the objects... groan.
Edit 2: Please note that I said the whole request including method, path, headers etc. The current responses only look at the body streams which does not include this information.
Edit 3: Does nobody read questions around here? Five answers so far and yet not one even hints at a way to get the whole raw on-the-wire request. Yes, I know I can capture the output streams and the headers and the URL and all that stuff from the request object. I already said that in the question, see:
I can re-constitute what I believe the request looks like by inspecting all the properties of the HttpRequest object and building a string from them (and similarly for the response) but I'd really like to get hold of the actual request/response data that's sent on the wire.
If you know the complete raw data (including headers, url, http method, etc.) simply cannot be retrieved then that would be useful to know. Similarly if you know how to get it all in the raw format (yes, I still mean including headers, url, http method, etc.) without having to reconstruct it, which is what I asked, then that would be very useful. But telling me that I can reconstruct it from the HttpRequest
/HttpResponse
objects is not useful. I know that. I already said it.
Please note: Before anybody starts saying this is a bad idea, or will limit scalability, etc., we'll also be implementing throttling, sequential delivery, and anti-replay mechanisms in a distributed environment, so database logging is required anyway. I'm not looking for a discussion of whether this is a good idea, I'm looking for how it can be done.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
一定要使用
IHttpModule
并实现BeginRequest
和EndRequest
事件。所有“原始”数据都存在于
HttpRequest
和HttpResponse
之间,只是不是单一的原始格式。 以下是构建 Fiddler 风格转储所需的部分(大约尽可能接近原始 HTTP):对于响应:
请注意,您无法读取响应流,因此您必须添加一个过滤器输出流并捕获副本。
在
BeginRequest
中,您需要添加一个响应过滤器:将
filter
存储在您可以在EndRequest
处理程序中访问的位置。 我建议在HttpContext.Items
中。 然后可以在filter.ReadStream()
中获取完整的响应数据。然后使用装饰器模式作为流的包装器来实现OutputFilterStream:
Definitely use an
IHttpModule
and implement theBeginRequest
andEndRequest
events.All of the "raw" data is present between
HttpRequest
andHttpResponse
, it just isn't in a single raw format. Here are the parts needed to build Fiddler-style dumps (about as close to raw HTTP as it gets):For the response:
Note that you cannot read the response stream so you have to add a filter to the Output stream and capture a copy.
In your
BeginRequest
, you will need to add a response filter:Store
filter
where you can get to it in theEndRequest
handler. I suggest inHttpContext.Items
. There can then get the full response data infilter.ReadStream()
.Then implement
OutputFilterStream
using the Decorator pattern as a wrapper around a stream:HttpRequest 上的以下扩展方法将创建一个可以粘贴到 fiddler 中并重播的字符串。
The following extension method on HttpRequest will create a string that can be pasted into fiddler and replayed.
您可以使用 ALL_RAW 服务器变量来获取随请求发送的原始 HTTP 标头,然后您可以照常获取 InputStream:
查看: http://msdn.microsoft.com/en-us/library/ms524602%28VS.90%29.aspx
You can use the ALL_RAW server variable to get the original HTTP headers sent with the request, then you can get the InputStream as usual:
check out: http://msdn.microsoft.com/en-us/library/ms524602%28VS.90%29.aspx
好吧,我正在开发一个项目,并使用请求参数进行了日志记录(也许不是太深):
看一下:
您可以装饰控制器类以完全记录它:
或仅记录一些单独的操作方法
Well, I'm working on a project and did, maybe not too deep, a log using the request params:
Take a look:
You can decorate your controllers class for log it entirely:
or log just some individual action methods
您需要将其保留在托管代码中有什么原因吗?
值得一提的是,您可以启用 如果您不喜欢重新发明轮子,则在 IIS7 中跟踪日志记录失败。 这会记录标头、请求和响应正文以及许多其他内容。
Any reason you need to keep it in managed code?
It is worth mentioning that you can enable Failed Trace logging in IIS7 if you don't like re-inventing the wheel. This logs headers, the request and response body as well as many other things.
我采用了 McKAMEY 的方法。 这是我编写的一个模块,可以帮助您入门并希望为您节省一些时间。 显然,您需要使用适合您的东西来插入记录器:
I went with McKAMEY's approach. Here's a module I wrote that will get you started and hopefully save you some time. You'll need to plug the Logger obviously with something that works for you:
好的,所以看起来答案是“不,你无法获取原始数据,你必须根据解析对象的属性重建请求/响应”。 哦,好吧,我已经完成了重建工作。
OK, so it looks like the answer is "no you can't get the raw data, you have to reconstruct the request/response from the properties of the parsed objects". Oh well, I've done the reconstruction thing.
使用 IHttpModule:
use a IHttpModule:
如果偶尔使用,为了绕过困境,像下面这样简单的东西怎么样?
if for occasional use, to get around a tight corner, how about something crude like below?
您可以在
DelegatingHandler
中完成此操作,而无需使用 .NET 4.5 中其他答案中提到的OutputFilter
,使用Stream.CopyToAsync()
函数。我不确定细节,但它不会触发您尝试直接读取响应流时发生的所有不好的事情。
例子:
You can accomplish this in a
DelegatingHandler
without using theOutputFilter
mentioned in other answers in .NET 4.5 using theStream.CopyToAsync()
function.I'm not sure on the details, but it does not trigger all of the bad things that happen when you attempt to directly read the response stream.
Example:
MVC 之前的
HttpRequest
和HttpResponse
曾经有一个GetInputStream()
和GetOutputStream()
可用于此目的目的。 还没有研究过 MVC 中的那些部分,所以我不确定它们是否可用,但可能是一个想法:)HttpRequest
andHttpResponse
pre MVC used to have aGetInputStream()
andGetOutputStream()
that could be used for that purpose. Haven't look into those part in MVC so Im not sure they are availavle but might be an idea :)我知道它不是托管代码,但我会建议使用 ISAPI 过滤器。 自从我有幸维护自己的 ISAPI 以来已经有几年了,但据我记得,无论是在 ASP.Net 完成它之前还是之后,您都可以访问所有这些东西。
http://msdn.microsoft.com/en-us/library/ms524610。 aspx
如果 HTTPModule 不足以满足您的需要,那么我认为没有任何托管方法可以按所需的详细程度执行此操作。 虽然这样做会很痛苦。
I know it's not managed code, but I'm going to suggest an ISAPI filter. It's been a couple of years since I've had the "pleasure" of maintaining my own ISAPI but from what I recall you can get access to all this stuff, both before and after ASP.Net has done it's thing.
http://msdn.microsoft.com/en-us/library/ms524610.aspx
If a HTTPModule isn't good enough for what you need, then I just don't think there is any managed way of doing this in the required amount of detail. It's gonna be a pain to do though.
我同意其他人的观点,使用 IHttpModule。 看看这个问题的答案,它的作用与您所问的几乎相同。 它记录请求和响应,但没有标头。
如何跟踪 ScriptService WebService 请求?
I agree with the others, use an IHttpModule. Take a look at the answer to this question, which does almost the same thing that you are asking. It logs the request and response, but without headers.
How to trace ScriptService WebService requests?
最好在应用程序之外执行此操作。 您可以设置反向代理来执行类似的操作(以及更多操作)。 反向代理基本上是位于服务器机房中的 Web 服务器,位于 Web 服务器和客户端之间。 请参阅http://en.wikipedia.org/wiki/Reverse_proxy
It might be best to do this outside of your application. You can set up a reverse proxy to do things like this (and much more). A reverse proxy is basically a web server that sits in your server room, and stands between your web server(s) and the client. See http://en.wikipedia.org/wiki/Reverse_proxy
同意 FigmentEngine 的观点,
IHttpModule
似乎是可行的方法。查看
httpworkerrequest
、readentitybody
和GetPreloadedEntityBody
。要获取
httpworkerrequest
,您需要执行以下操作:其中
inApp
是 httpapplication 对象。Agree with FigmentEngine,
IHttpModule
appears to be the way to go.Look into
httpworkerrequest
,readentitybody
andGetPreloadedEntityBody
.To get the
httpworkerrequest
you need to do this:where
inApp
is the httpapplication object.