2010-09-27 10 views
47

Sé que todos van a responder "usar un servidor proxy de depuración como Fiddler", pero no es tan simple.¿Cómo veo la solicitud HTTP sin formato que envía la clase HttpWebRequest?

Aquí está mi situación: Tengo un código que se ejecuta en un servidor, en una página ASP.NET de código subyacente (aspx.cs), que (entre otras cosas) establece una conexión con otro servidor , ase un poco cosas, y luego formatea y lo devuelve al navegador.

El problema es que el otro servidor está haciendo lo incorrecto, y quiero poder pasar una bandera de depuración a la página (a través de la cadena de consulta, por ejemplo? Debug = true) para que se imprima el completamente crudo solicitud HTTP que está enviando al otro servidor para que pueda ver qué diablos está mal. Este código se está ejecutando en varios lugares, así que quiero poder pasar esta bandera en desarrollo, puesta en escena o producción y simplemente ver la solicitud, sin tener que averiguar si los servidores de producción pueden hablar con algún servidor proxy que exista en algún lugar , etc.

Pensarías que sería fácil hacerlo, ¿no? Así que siento que estoy loco o algo así, pero miré la referencia de HttpWebRequest y su clase de padres WebRequest y - nada. No se puede hacer. Pensarías que Microsoft habría pensado en esto. Lo más parecido es que puedes acceder a la colección "Encabezados", pero cuando lo probé omitió algunos encabezados realmente importantes como "longitud del contenido", así que debe estar "mintiéndome" (sé que está mintiendo, porque sé que es un hecho que el servidor remoto devuelve un estado 200 - la solicitud tiene éxito, es simplemente volviendo malos datos/diferentes/equivocadas)

Aquí está el ejemplo de código preguntadas para:

HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://www.whatever.com"); 
req.Method = ... whatever ...; 
... other setup for the request ... 
/* At this point we are about to send the request. 
    What does the raw HTTP request look like? */ 
HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); 
+1

¿Es posible reemplazar HttpWebRequest con algún otro componente? En caso afirmativo, puede tomar un componente HTTP de terceros que le permita capturar lo que se envía (o los encabezados) para hacer el trabajo. –

+0

¿Has probado Firebug para Firefox? Es bastante poderoso, no sé cómo se compara con Fiddler, pero tal vez tiene lo que necesitas. – Gallen

+8

Firebug no será de ayuda, ya que la parte interesante ocurre entre dos servidores: Firebug se encuentra dentro de Firefox, y solo puede inspeccionar lo que ocurre entre un servidor y el cliente. – tdammers

Respuesta

15

Puede usar el mecanismo de rastreo System.Net para ver las solicitudes HTTP sin procesar enviadas por el cable. También puede agregar su propio tracelistener al proceso.

+0

No lo he intentado, parece una buena opción. ¡Gracias! – eeeeaaii

+0

no funcionó para mí por alguna razón, aunque esta parece ser la mejor respuesta de todos modos (no me quitaré la marca de verificación). Ver mi publicación aquí: http://stackoverflow.com/questions/3822941/net-tracing-not-working-with-diagnostics-tracesource-only-diagnostics-trace – eeeeaaii

+0

Hmm .. Esto siempre me ha funcionado, por supuesto - Siempre hago aplicaciones de consola. ¿Se asegura de que haya otorgado acceso de escritura de identidad (cuenta) a ASP.NET al archivo/directorio donde desea que se escriba la salida de rastreo? – feroze

5

Usted puede usar un rastreador de tráfico de red como wireshark.

Esto no es un proxy de depuración, pero husmeará todo el tráfico y le permitirá ver las solicitudes sin procesar/respuestas.

+0

Si eso es similar a los rastreadores de paquetes típicos que he instalado en mi casa en el pasado, eso probablemente requeriría un nivel de acceso de administrador que no tengo aquí en el trabajo. No podría usarlo aquí en la oficina porque, para decirlo simplemente, podría leer los correos electrónicos de mis jefes. Irónicamente, podría ser más fácil obtener acceso de administrador si pudiera usar el escritorio remoto en los servidores de producción, pero el problema es que no tengo acceso a ellos en absoluto, ni siquiera para enviar archivos (otra empresa lo hace). – eeeeaaii

+1

Simplemente usaría la técnica que he descrito anteriormente: instale un Tracelistener en su dominio de aplicación usando un archivo web.config, y solicite al tracelistener que escriba el flujo de depuración en el disco local o en el webpate que luego se procesa en el cliente. – feroze

+0

He encontrado que Fiddler (http://fiddler2.com/) es una solución muy simple para este problema. –

1

Otra sugerencia. Implement your own web proxy, y configure su solicitud para usarlo con WebRequest.Proxy. Entonces debería poder extraer el tráfico de la instancia de proxy.

Editar: actualización de enlaces.

+0

Sí, pensé en hacer eso, parece que tal vez sea la única forma. Pero introduce mucha complejidad. Digamos que implemento un proxy web que se encuentra en el mismo servidor que el sitio. ¿Qué hace con la salida? ¿Lo registra en un archivo? ¿Hay alguna forma de conectarse al proxy y ver el registro, dado que no tengo acceso al servidor? Creo que sería difícil o imposible configurar esto en el servidor de producción porque requeriría abrir un nuevo puerto para dirigir el tráfico proxy, y eso no sería permitido por los administradores. – eeeeaaii

+0

Bueno, el proxy podría rechazar todas las solicitudes que no se originen en la máquina local. No necesita abrir el puerto al mundo exterior. Puede hacer todo esto o solo las solicitudes a través del proxy solo en una sección #IF DEPURACIÓN. Haga que se registre en el registro de eventos o en un archivo, y luego haga que la producción le envíe los registros. Es lo mejor que puedes hacer, aparte de pedirles que ejecuten Fiddler en la máquina de producción por ti. Personalmente, presionaría por esto (ellos ejecutando Fiddler), sinceramente, si eso significa ahorrar tiempo y dinero en lugar de lanzar su propio registrador proxy en proceso, en serio. –

+0

Además, ¿puede configurar los servidores de prueba que imitan su entorno de producción utilizando algunas máquinas virtuales? ¿El problema realmente solo se limita a esta máquina? –

0

Dice que cree que .NET le miente, y el ejemplo específico que da es que falta el encabezado Content-Length en la respuesta HTTP.

Pero el encabezado Content-Length no es necesario a partir de una respuesta HTTP. De hecho, si el cuerpo de la respuesta está en cualquier dinámica, y si su longitud no se conoce de antemano, entonces es muy probable que se omita el encabezado Content-Length.

+0

Estoy hablando de solicitudes, no de respuestas. Esta es la prueba que realicé: ejecuté el programa, hice una solicitud http y obtuve una respuesta. Luego, hice una solicitud a mano (en violín) basada en la información exacta que .NET me dijo que estaba enviando (imprimiendo HttpWebRequest.Headers, HttpWebRequest.Method, etc.). Específicamente, esta solicitud omite Content-Length. Pero el servidor volvió con un error que indicaba que se requería Content-Length (lo que tiene sentido, ya que era una solicitud POST). Por lo tanto, tengo problemas para confiar en lo que informa .NET. – eeeeaaii

+0

p.s. Además, el mismo código .NET exacto informó un conjunto diferente de encabezados cuando lo ejecuté en dos servidores que tenían dos versiones diferentes de .NET. Ahora quizás las dos versiones de .NET en realidad estaban produciendo diferentes encabezados, IDK. Pero me hace sospechar, sin embargo, y me gustaría un vertedero en bruto. – eeeeaaii

+0

http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 - 'Content-Length' NO se debe dar en una serie de circunstancias, incluso cuando se utiliza la codificación de transferencia fragmentada. ¿El servidor de destino es compatible con HTTP/1.1? – yfeldblum

4

respondiendo a mi pregunta aquí, porque pensé en otra forma de hacerlo. Básicamente, la idea es que reasignas HttpWebRequest a una página que registra la solicitud HTTP sin procesar entrante.En otras palabras configurar un controlador HTTP personalizado según este mensaje del foro:

http://forums.asp.net/t/353955.aspx

Y luego cambiar simplemente la URL en el HttpWebRequest para apuntar a este nuevo punto final, pero mantener todos los otros elementos de la solicitud de la misma . Escribe el resultado en un archivo o algo y estás dorado.

92

Me doy cuenta de que esta es una vieja pregunta @feroze responde que hacer esto pero no entra en detalles sobre cómo configurar el seguimiento de System.Net para lograr esto, ya que esta pregunta fue el primer resultado de google para mi consulta el tema, ya que todos estamos ocupados, pensé que podría salvarlos a todos de tener que buscar esta información.

System.web es muy potente para depurar HttpWebRequest y se puede configurar fácilmente mediante el web.config

<configuration> 
    <system.diagnostics> 

     <trace autoflush="true" /> 

     <sources> 
      <source name="System.Net" maxdatasize="1024"> 
       <listeners> 
        <add name="MyTraceFile"/> 
        <add name="MyConsole"/> 
       </listeners> 
      </source> 
     </sources> 

     <sharedListeners> 
      <add 
       name="MyTraceFile" 
       type="System.Diagnostics.TextWriterTraceListener" 
       initializeData="System.Net.trace.log" /> 
       <add name="MyConsole" type="System.Diagnostics.ConsoleTraceListener" /> 
     </sharedListeners> 

     <switches> 
      <add name="System.Net" value="Verbose" /> 
     </switches> 

    </system.diagnostics> 
</configuration> 

Un HttpWebRequest simple en su código, y funcionando en modo de depuración en Visual Studio, la siguiente información se se mostrará en la consola de depuración.

System.Net Verbose: 0 : [6596] WebRequest::Create(https://example.com/service.asmx) 
System.Net Verbose: 0 : [6596] HttpWebRequest#62063506::HttpWebRequest(https://example.com/service.asmx#11234) 
System.Net Information: 0 : [6596] RAS supported: True 
System.Net Verbose: 0 : [6596] Exiting HttpWebRequest#11234::HttpWebRequest() 
System.Net Verbose: 0 : [6596] Exiting WebRequest::Create()  -> HttpWebRequest#11234 
System.Net Verbose: 0 : [6596] HttpWebRequest#11234 ::GetRequestStream() 
System.Net Verbose: 0 : [6596] ServicePoint#11234 ::ServicePoint(example.com:443) 
System.Net Information: 0 : [6596] Associating HttpWebRequest#11234with ServicePoint#11234 
System.Net Information: 0 : [6596] Associating Connection#11234 with HttpWebRequest#11234 
System.Net Information: 0 : [6596] Connection#11234 - Created connection from x.x.x.x:xx to x.x.x.x:xx. 
System.Net Information: 0 : [6596] TlsStream#11234 ::.ctor(host=example.com, #certs=0) 
System.Net Information: 0 : [6596] Associating HttpWebRequest#11234 with ConnectStream#11234 
System.Net Verbose: 0 : [6596] Exiting HttpWebRequest#11234 ::GetRequestStream() -> ConnectStream#11234 
System.Net Verbose: 0 : [6596] ConnectStream#7740977::Write() 
System.Net Verbose: 0 : [6596] Data from ConnectStream#11234::Write 
System.Net Verbose: 0 : [6596] 00000000 : 3C 73 6F 61 70 3A 45 6E-76 65 6C 6F 70 65 0D 0A : <soap:Envelope.. 
...etc 

me encontré con esto especialmente útil cuando se trata de averiguar la causa de un error de cliente de servicio web, resultó que estaba perdiendo un encabezado.

+4

Wow. Esta pequeña utilidad fue EXACTAMENTE lo que necesitaba. Tenía un programa de consola haciendo solicitudes de publicación que funcionaba perfectamente pero una aplicación ASP.NET WebForm que estaba fallando con las mismas solicitudes. ¡Esta utilidad me mostró la diferencia en la solicitud de POST en bruto, que es lo que necesitaba! Solo agregándolo a los archivos web.config y app.config según corresponda. Gracias kamui! –

+0

Muy bien, gracias @kamui. –

+2

Mucho más conveniente que tener que preocuparse por configurar/usar Fiddler o Wireshark. – Sabuncu

-1

Me falta algo, porque obtener la solicitud HTTP sin procesar como texto ASCII es realmente fácil, siempre que lo tome en Page_Init() será diferente por Page_Load().

protected void Page_Init(object sender, EventArgs e) 
{ 
    //this gets the raw request as an ASCII String. 
    byte[] biData = Request.BinaryRead(Request.TotalBytes); 
    string sWholeRequestAsString = System.Text.Encoding.ASCII.GetString(biData); 

} 
+1

Sí, definitivamente te estás perdiendo algo, como toda la pregunta. Está hablando de hacer una solicitud al usar C $ utilizando la clase HTtpWebRequest, no una solicitud de página webforms. –

Cuestiones relacionadas