Estou escrevendo um serviço da Web (usando o ASP.NET MVC) e, para fins de suporte, gostaríamos de poder registrar as solicitações e respostas o mais próximo possível do formato bruto on-the-wire (ou seja, incluindo HTTP método, caminho, todos os cabeçalhos e o corpo) em um banco de dados.
O que não tenho certeza é como se apossar desses dados da maneira menos 'confusa'. Posso reconstituir a aparência da solicitação, inspecionando todas as propriedades do HttpRequest
objeto e construindo uma string a partir delas (e da mesma forma para a resposta), mas eu realmente gostaria de me apossar dos dados reais de solicitação / resposta que são enviado no fio.
É um prazer usar qualquer mecanismo de interceptação, como filtros, módulos, etc., e a solução pode ser específica ao IIS7. No entanto, eu preferiria mantê-lo apenas no código gerenciado.
Alguma recomendação?
Editar: notei que HttpRequest
possui um SaveAs
método que pode salvar a solicitação em disco, mas isso reconstrói a solicitação a partir do estado interno usando uma carga de métodos auxiliares internos que não podem ser acessados publicamente (por que isso não permite salvar em um usuário fornecido) fluxo que eu não sei). Então está começando a parecer que vou ter que fazer o meu melhor para reconstruir o texto da solicitação / resposta dos objetos ... gemer.
Editar 2: Observe que eu disse que toda a solicitação, incluindo método, caminho, cabeçalhos, etc. As respostas atuais apenas examinam os fluxos do corpo que não incluem essas informações.
Edit 3: Ninguém lê perguntas por aqui? Cinco respostas até o momento e ainda nem uma delas sugere uma maneira de obter todo o pedido bruto on-the-wire. Sim, eu sei que posso capturar os fluxos de saída e os cabeçalhos, a URL e todas essas coisas do objeto de solicitação. Eu já disse isso na pergunta, veja:
Posso reconstituir a aparência da solicitação, inspecionando todas as propriedades do objeto HttpRequest e construindo uma string a partir delas (e da mesma forma para a resposta), mas eu realmente gostaria de me apossar dos dados reais da solicitação / resposta que é enviado pelo fio.
Se você souber que os dados brutos completos (incluindo cabeçalhos, URL, método http etc.) simplesmente não podem ser recuperados, isso seria útil. Da mesma forma, se você souber como obter tudo no formato bruto (sim, eu ainda quero dizer incluindo cabeçalhos, URL, método http, etc.) sem precisar reconstruí-lo, como pedi, isso seria muito útil. Mas me dizer que posso reconstruí-lo a partir de HttpRequest
/ HttpResponse
objects não é útil. Eu sei disso. Eu já disse isso.
Observação: antes que alguém comece a dizer que é uma má idéia ou que limite a escalabilidade, etc., também estaremos implementando mecanismos de otimização, entrega sequencial e anti-replay em um ambiente distribuído, de modo que o log do banco de dados seja necessário. Não estou à procura de uma discussão sobre se essa é uma boa ideia, estou procurando como isso pode ser feito.
fonte
Respostas:
Definitivamente usar um
IHttpModule
e implementar asBeginRequest
eEndRequest
eventos.Todos os dados "brutos" estão presentes entre
HttpRequest
eHttpResponse
simplesmente não estão em um único formato bruto. Aqui estão as partes necessárias para criar dumps no estilo Fiddler (o mais próximo possível do HTTP bruto):Para a resposta:
Observe que você não pode ler o fluxo de resposta, portanto, você deve adicionar um filtro ao fluxo de Saída e capturar uma cópia.
No seu
BeginRequest
, você precisará adicionar um filtro de resposta:Armazene
filter
onde você pode acessá-lo noEndRequest
manipulador. Eu sugiroHttpContext.Items
. Em seguida, é possível obter os dados completos da respostafilter.ReadStream()
.Em seguida, implemente
OutputFilterStream
usando o padrão Decorator como um wrapper em torno de um fluxo:fonte
O seguinte método de extensão no HttpRequest criará uma sequência que pode ser colada no violinista e reproduzida.
fonte
HttpRequestBaseExtensions
e para mudarHttpRequest
paraHttpRequestBase
a cada lugar.Você pode usar a variável do servidor ALL_RAW para obter os cabeçalhos HTTP originais enviados com a solicitação e obter o InputStream como de costume:
confira: http://msdn.microsoft.com/en-us/library/ms524602%28VS.90%29.aspx
fonte
HttpContext.Current.Request
para pegar o exterior contexto atual de controladores MVC, páginas ASPX, etc ... apenas certifique-se que não é nulo o primeiro;)Bem, estou trabalhando em um projeto e fiz, talvez não muito profundo, um log usando os parâmetros de solicitação:
Dê uma olhada:
Você pode decorar sua classe de controladores para registrá-la inteiramente:
ou registre apenas alguns métodos de ação individuais
fonte
Algum motivo para você precisar mantê-lo no código gerenciado?
Vale ressaltar que você pode habilitar o log do Failed Trace no IIS7 se não gostar de reinventar a roda. Isso registra os cabeçalhos, o corpo da solicitação e resposta, além de muitas outras coisas.
fonte
GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
no final deRegister(..)
inWebApiConfig.cs
, mas isso pode variar entre as versões.Eu fui com a abordagem de McKAMEY. Aqui está um módulo que escrevi para você começar e, com sorte, economizar algum tempo. Você precisará conectar o Logger obviamente a algo que funcione para você:
fonte
Encoding.UTF8
, ou talvezEncoding.Default
ao ler o fluxo de solicitações? Ou apenas use umStreamReader
( com ressalvas )OK, então parece que a resposta é "não, você não pode obter os dados brutos, é necessário reconstruir a solicitação / resposta a partir das propriedades dos objetos analisados". Oh, bem, eu fiz a coisa da reconstrução.
fonte
use um IHttpModule :
fonte
se para uso ocasional, para contornar um canto apertado, que tal algo bruto como abaixo?
fonte
Você pode fazer isso
DelegatingHandler
sem usar oOutputFilter
mencionado em outras respostas no .NET 4.5 usando aStream.CopyToAsync()
funçãoNão tenho certeza dos detalhes, mas ele não aciona todas as coisas ruins que acontecem quando você tenta ler diretamente o fluxo de resposta.
Exemplo:
fonte
Sei que não é um código gerenciado, mas vou sugerir um filtro ISAPI. Faz alguns anos desde que tive o "prazer" de manter meu próprio ISAPI, mas pelo que me lembro, você pode ter acesso a todas essas coisas, antes e depois do ASP.Net ter feito isso.
http://msdn.microsoft.com/en-us/library/ms524610.aspx
Se um HTTPModule não é bom o suficiente para o que você precisa, simplesmente não acho que exista uma maneira gerenciada de fazer isso na quantidade necessária de detalhes. Vai ser uma dor de fazer embora.
fonte
Eu concordo com os outros, use um IHttpModule. Dê uma olhada na resposta a esta pergunta, que faz quase a mesma coisa que você está fazendo. Ele registra a solicitação e a resposta, mas sem cabeçalhos.
Como rastrear solicitações de ScriptService WebService?
fonte
Talvez seja melhor fazer isso fora do seu aplicativo. Você pode configurar um proxy reverso para fazer coisas assim (e muito mais). Um proxy reverso é basicamente um servidor da Web que fica na sua sala de servidores e fica entre o (s) servidor (es) da Web e o cliente. Veja http://en.wikipedia.org/wiki/Reverse_proxy
fonte
Concordo com o FigmentEngine,
IHttpModule
parece ser o caminho a seguir.Olhar para
httpworkerrequest
,readentitybody
eGetPreloadedEntityBody
.Para obter o que
httpworkerrequest
você precisa, faça o seguinte:onde
inApp
está o objeto httpapplication.fonte
HttpRequest
e oHttpResponse
MVC pré costumava ter umGetInputStream()
eGetOutputStream()
que poderia ser usado para esse fim. Não olhei para as partes do MVC, então não tenho certeza de que elas estejam disponíveis, mas pode ser uma ideia :)fonte