2011-03-18 2 views
7

J'ai récemment découvert que ce qui suit ne fonctionne pas avec certains sites, tels que IMDB.com.WebRequest "HEAD" alternative de poids léger

class Program 
    { 
     static void Main(string[] args) 
     { 
      try 
      { 
       System.Net.WebRequest wc = System.Net.WebRequest.Create("http://www.imdb.com"); //args[0]); 

       ((HttpWebRequest)wc).UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/0.2.153.1 Safari/525.19"; 
       wc.Timeout = 1000; 
       wc.Method = "HEAD"; 
       WebResponse res = wc.GetResponse(); 
       var streamReader = new System.IO.StreamReader(res.GetResponseStream()); 

       Console.WriteLine(streamReader.ReadToEnd()); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.Message); 
      } 
     } 
    } 

Il renvoie un HTTP 405 (méthode non autorisée). Mon problème est, j'utilise un code très similaire à celui ci-dessus pour vérifier si un lien est valide et la grande majorité des fois cela fonctionne correctement. Je peux passer à la méthode GET égale et cela fonctionne (avec une augmentation de timeout), mais cela ralentit les choses d'un ordre de grandeur. Je suppose que la réponse 405 est une configuration de serveur du côté serveur d'IMDB.

Existe-t-il un moyen pour moi de faire la même chose que ci-dessus, d'une manière légère dans .NET? Ou, est-il un moyen de corriger le code ci-dessus afin qu'il fonctionne comme une requête GET qui fonctionne avec imdb?

+1

J'ai dû augmenter le timeout, mais le code que vous avez posté ci-dessus fonctionne pour moi. Le modifier en POST n'aurait aucun sens, car vous n'avez aucune donnée à publier. Et votre titre parle de HEAD, mais vous ne faites pas une demande HEAD. S'il vous plaît clarifier quelle est la question, puisque votre code "cassé" fonctionne bien. –

+0

Ug, typo vraiment stupide dans le titre. Fixé maintenant ... exemple classique de penser une chose et en taper une autre. Lorsque vous exécutez le code ci-dessus, vous n'obtenez pas une réponse 405? EDIT: Ok, réalisé même mon code était défectueux. Ce qui précède est ce que je voulais publier, et est édité pour donner l'erreur 405 (et faire sens .....) – Serapth

Répondre

3

Vous devrez clarifier ce que vous entendez par "léger". Qu'est-ce que vous essayez d'accomplir?

L'utilisation ou non de GET/POST/HEAD/DELETE/etc dépendra de l'URL et de ce qui est configuré dans l'application exécutée sur le serveur à cette adresse URL. Si tout ce que vous essayez de faire est de voir si vous pouvez établir une connexion sans réellement télécharger le contenu, vous pouvez essayer simplement d'initier une connexion au port 80 en utilisant sockets, mais il n'y a pas de manière vraiment fiable ou universellement supportée juste en changeant la méthode HTTP.

+0

Eh bien essentiellement ce que j'utilise la demande HEAD pour maintenant sont a) pour vérifier si un site existe réellement b) si un site existe, pour chaque lien à l'intérieur, vérifiez qu'ils existent réellement (donc chaque image, feuille de style, etc ...). Par conséquent, sur certaines pages lourdes d'image, il pourrait littéralement être appelé des centaines de fois. Donc, par léger, je veux dire principalement le trafic réseau. – Serapth

+1

Droit ...La seule méthode plus légère que je pourrais penser en ce qui concerne la bande passante serait d'utiliser des sockets pour construire manuellement vos requêtes HTTP, récupérer assez de la réponse pour déterminer le code d'état HTTP, puis fermez la connexion. –

+0

Est-ce que le fait de faire un routage HTTP à la main permettrait de contourner les résultats de l'erreur 405? EDIT: Euh, les résultats de statut que j'aurais dû dire, je suppose que techniquement, le protocole HTTP 405 n'est pas une erreur. C'est seulement une poignée de sites qui retournent 405, et je ne sais pas vraiment quelle partie provoque cette réponse. En ce moment, je suppose que c'est la demande HEAD, mais je ne suis pas sûr. – Serapth

6

Ouvrez la connexion vous-même avec un socket (au lieu d'un HttpRequest ou WebClient), et fermez le flux dès que vous avez lu le code d'état. Heureusement, le code d'état arrive en haut du flux de réponse :)

4

Si HEAD renvoie un 405, cela signifie que le serveur ne prend pas en charge HEAD (au moins pour cette URL) et que vous devrez retomber à GET à la place. . La majorité des sites devraient supporter HEAD, donc vous voudrez probablement faire HEAD par défaut, mais si vous lancez un 405, vous pourriez peut-être revenir à GET pour ce domaine. Ou peut-être que vous voulez essayer HEAD d'abord pour chaque demande; YMMV.

Si le serveur nécessite GET et que vous souhaitez réduire le trafic réseau, vous pouvez essayer de créer un GET conditionnel et/ou un GET partiel (voir par exemple RFC2616). Je n'ai jamais essayé de faire cela avec WebRequest mais je pense qu'il vous permet d'ajouter des en-têtes HTTP sortants personnalisés, donc vous devriez être capable de le faire. De plus, n'oubliez pas que si vous écrivez une araignée (ce que vous êtes clairement), vous devriez respecter le fichier robots.txt du serveur, et il est également courtois de limiter vos demandes à quelque chose comme une demande tous les deux ans. secondes, de sorte que vous ne slashdot le serveur.

+0

Merci pour la réponse. Je ne suis pas en train d'écrire une araignée, le produit final est plus proche de la nature d'un navigateur Web qu'autre chose. J'ai fait comme vous l'avez suggéré plus tôt (requête HEAD, puis sur 405 un GET complet), ce qui est ma façon actuelle de faire les choses mais c'est sous-optimal. Je vais regarder dans les GET partiels, ce serait probablement parfait. Merci. – Serapth

Questions connexes