web-dev-qa-db-fra.com

Comment puis-je voir la requête HTTP brute envoyée par la classe HttpWebRequest?

Je sais que vous allez tous répondre "utilisez un serveur proxy de débogage comme Fiddler" mais ce n'est pas si simple.

Voici ma situation: j'ai du code qui s'exécute sur un serveur, dans une page ASP.NET code-behind (aspx.cs), qui (entre autres) établit une connexion avec n autre serveur, saisit certains trucs, puis le formate et le renvoie au navigateur.

Le problème est que l'autre serveur fait la mauvaise chose, et je veux donc pouvoir passer un indicateur de débogage dans la page (via la chaîne de requête, par exemple? Debug = true) afin qu'il imprime le complètement brut demande HTTP qu'il envoie à l'autre serveur afin que je puisse voir ce qui ne va pas. Ce code s'exécute à plusieurs endroits, je veux donc pouvoir simplement passer ce drapeau sur le développement, la mise en scène ou la production et simplement voir la demande, sans avoir à déterminer si les serveurs de production peuvent parler à un serveur proxy qui existe quelque part , etc.

On pourrait penser qu'il serait facile de faire cela, non? Donc je me sens comme un fou ou quelque chose comme ça mais j'ai regardé la référence pour HttpWebRequest et sa classe parent WebRequest et - rien. Ne peut faire. On pourrait penser que Microsoft aurait pensé à cela. La chose la plus proche est que vous pouvez accéder à la collection "Headers" mais quand je l'ai essayée, elle a omis des en-têtes vraiment importants comme "content length" - donc ça doit être "mentir" pour moi (je sais que c'est mentir, parce que je sais pour un fait que le serveur distant renvoie un état 200 - la demande est réussie, elle renvoie simplement des données incorrectes/différentes/erronées)

Voici l'exemple de code demandé:

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();
63
eeeeaaii

Vous pouvez utiliser le mécanisme de suivi System.Net pour voir les requêtes HTTP brutes envoyées sur le câble. Vous pouvez également ajouter votre propre tracelistener au processus.

14
feroze

Je me rends compte que c'est une vieille question. réponse de @ feroze dit quoi faire, mais n'entre pas dans les détails sur la configuration de System.Net traçage pour y parvenir.

Comme cette question était le premier résultat de Google pour ma requête sur le sujet, et comme nous sommes tous des gens occupés, j'ai pensé que je vous éviterais tous de devoir traquer ces informations.

System.Web est très puissant pour le débogage HttpWebRequests et peut être facilement configuré à l'aide de 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>

En ajoutant un simple HttpWebRequest dans votre code et en exécutant en mode débogage dans Visual Studio, les informations suivantes seront affichées dans la console de débogage:

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

J'ai trouvé cela particulièrement utile lorsque j'essayais de trouver la cause d'une erreur du client de service Web. Il s'est avéré qu'il me manquait un en-tête.

125
kamui

Vous pouvez utiliser un renifleur de trafic réseau comme WireShark .

Ce n'est pas un proxy de débogage, mais il reniflera tout le trafic et vous permettra de voir les demandes/réponses brutes.

5
Oded

répondre à ma propre question ici, parce que je pensais à une autre façon de le faire. Fondamentalement, l'idée est - vous redirigez le HttpWebRequest vers une page qui enregistre la requête HTTP brute entrante. En d'autres termes, configurez un gestionnaire HTTP personnalisé conformément à ce message sur le forum:

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

Modifiez ensuite uniquement l'URL dans HttpWebRequest pour pointer vers ce nouveau point de terminaison, mais conservez tous les autres éléments de la demande. Écrivez le résultat dans un fichier ou quelque chose et vous êtes en or.

4
eeeeaaii

Je vous suggère de télécharger Telerik Fiddler pour capturer le trafic entrant/sortant.

Ici est un exemple simple comment le faire avec cet outil:

  1. Assurez-vous que le trafic de capture est activé: enter image description here
  2. Ouvrez le navigateur et actualisez la page, ou envoyez simplement une demande via le client HTTP. enter image description here
  3. Après ce passage au Fiddler, vous devriez voir votre demande: enter image description here
  4. En haut, essayez de naviguer dans l'onglet "Raw". enter image description here
  5. Dans la fenêtre ci-dessous se trouve votre demande brute enter image description here
3
Mroczny Arturek

Une autre suggestion. Implémentez votre propre proxy Web , et définissez votre demande pour l'utiliser avec WebRequest.Proxy . Ensuite, vous devriez pouvoir extraire le trafic de l'instance proxy.

Edit: mise à jour des liens.

1
Mike Atlas

Je sais que c'est une vieille question, mais j'étais dans une situation difficile où je ne contrôlais pas le fichier de configuration de l'application, j'avais donc besoin d'un moyen simple pour activer le suivi via le code, puis accéder facilement aux données brutes de demande/réponse dans un un événement. J'ai donc mis en place cette classe personnalisée, HttpRawTraceListener, qui pourrait être utile à d'autres qui sont à ma place:

https://github.com/jhilgeman/HttpRawTraceListener/blob/master/HttpRawTraceListener.cs

Il a été conçu pour être aussi simple que d'ajouter le fichier à votre projet, puis d'appeler:

System.Diagnostics.HttpRawTraceListener.Initialize();

... pour commencer la trace. À partir de là, les demandes/réponses seront analysées à partir des messages de trace, puis rendues disponibles via l'événement System.Diagnostics.HttpRawTraceListener.FinishedCommunication .

Ce n'est probablement pas parfait à 100% pour chaque scénario (par exemple, ce n'est pas un proxy, donc il ne capturera pas les demandes Web à partir d'un navigateur, par exemple), mais cela fonctionne assez bien pour capturer les demandes/réponses HttpWebRequests aux services Web, et cela pourrait être un bon point de départ si vous avez besoin de quelque chose comme ça.

0
jhilgeman

Vous dites que vous pensez que .NET vous ment, et l'exemple spécifique que vous donnez est que l'en-tête Content-Length est absent de la réponse HTTP.

Mais l'en-tête Content-Length n'est pas requis à partir d'une réponse HTTP. En fait, si le corps de la réponse est dans une dynamique quelconque, et si sa longueur n'est pas connue à l'avance, il est fort probable que le Content-Length l'en-tête sera omis!

0
yfeldblum