2010-05-30 8 views
3

J'essaie d'envoyer par programme une requête POST à ​​un serveur Web afin de me connecter puis d'effectuer d'autres requêtes nécessitant une connexion.La réponse HttpWebRequest produit le protocole HTTP 422. Pourquoi?

Ceci est mon code:

byte[] data = Encoding.UTF8.GetBytes(
    String.Format(
     "login={0}&password={1}&authenticity_token={2}" 
     +"&login_submit=Entra&remember_me=1", 
     HttpUtility.UrlEncode(username), HttpUtility.UrlEncode(password), 
     HttpUtility.UrlEncode(token))); 

    //Create HTTP-request for login 
    HttpWebRequest request = 
      (HttpWebRequest)HttpWebRequest.Create("http://www.xxx.xx/xx/xx"); 

    request.Method = "POST"; 
    request.ContentType = "application/x-www-form-urlencoded"; 
    request.ContentLength = data.Length; 
    request.CookieContainer = new CookieContainer(); 

    request.Accept = "application/xml,application/xhtml+xml,text/html; 
        +"q=0.9,text/plain ;q=0.8,image/png,*/*;q=0.5"; 
    request.Referer = "http://www.garzantilinguistica.it/it/session"; 
    request.Headers.Add("Accept-Language", "de-DE"); 
    request.Headers.Add("Origin", "http://www.xxx.xx"); 
    request.UserAgent = "C#"; 
    request.Headers.Add("Accept-Encoding", "gzip, deflate"); 

Après l'envoi de la demande

//Send post request 
    var requestStream = request.GetRequestStream(); 

    requestStream.Write(data, 0, data.Length); 
    requestStream.Flush(); 
    requestStream.Close(); 

... Je veux obtenir la réponse des serveurs:

//Get Response 
    StreamReader responseStreamReader = new 
    StreamReader(
     request.GetResponse().GetResponseStream()); //WebException: HTTP 422! 
    string content = responseStreamReader.ReadToEnd(); 

Ce morceau de feux de code le WebException, qui me dit le serveur a répondu avec HTTP 422 (entité non traitable due à l'erreur sémantique s)

Puis j'ai comparé (à l'aide d'un sniffer TCP/IP) les requêtes de mon programme et du navigateur (ce qui bien sûr produit une requête POST valide et obtient la bonne réponse).

(1) Ma demande de programme:

POST /it/session HTTP/1.1 
Content-Type: application/x-www-form-urlencoded 
Accept: application/xml,application/xhtml+xml,text/html; 
q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 
Referer: http://www.garzantilinguistica.it/it/session 
Accept-Language: de-DE 
Origin: http://www.garzantilinguistica.it 
User-Agent: Test 
Accept-Encoding: gzip, deflate 
Host: www.garzantilinguistica.it 
Content-Length: 148 
Expect: 100-continue 
Connection: Keep-Alive 


HTTP/1.1 100 Continue 


login=thespider14%40hotmail.com&password=xxxxx&authenticity_token=4vLgtwP3nFNg4NeuG4MbUnU7sy4z91Wi8WJXH0POFmg%3d&login_submit=Entra&remember_me=1 

(2) La demande du navigateur:

POST /it/session HTTP/1.1 
    Host: www.garzantilinguistica.it 
    Referer: http://www.garzantilinguistica.it/it/session 
    Accept: application/xml,application/xhtml+xml,text/html;q=0.9, 
text/plain;q=0.8,image/png,*/*;q=0.5 
    Accept-Language: de-DE 
    Origin: http://www.garzantilinguistica.it 
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; de-DE) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7 
    Accept-Encoding: gzip, deflate 
    Content-Type: application/x-www-form-urlencoded 
    Cookie: __utma=244184339.652523587.1275208707.1275208707.1275211298.2; __utmb=244184339.20.10.1275211298; __utmc=244184339; __utmz=244184339.1275208707.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); _garzanti2009_session=BAh7CDoPc2Vzc2lvbl9pZCIlZDg4MWZjNjg2YTRhZWE0NDQ0ZTJmMTU2YWY4ZTQ1NGU6EF9jc3JmX3Rva2VuIjFqRWdLdll3dTYwOTVVTEpNZkt6dG9jUCtaZ0o4V0FnV2V5ZnpuREx6QUlZPSIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsGOgplcnJvciIVbG9naW4gbm9uIHZhbGlkbwY6CkB1c2VkewY7CFQ%3D--4200fa769898dd156faa49e457baf660cf068d08 
    Content-Length: 144 
    Connection: keep-alive 

authenticity_token=jEgKvYwu6095ULJMfKztocP%2BZgJ8WAgWeyfznDLzAIY%3D&login=thespider14%40hotmail.com&password=xxxxxx&remember_me=1&commit=Entra 
HTTP/1.1 302 Found 

aider quelqu'un peut comprendre quelle partie de la demande que je suis absent ou ce que le principal différence entre le navigateur et ma demande est? Pourquoi est-ce que j'obtiens ce 422?

EDIT:

je remarquai que ma demande contient un en-tête Expect avec la valeur 100-continue, alors que le navigateur ne fait pas de. J'ai mis le request.Expect-propriété à null et à "". Mais je ne pouvais tout simplement pas m'en débarrasser. Aucune suggestion? Que ceci soit la racine de tout mal?

EDIT:

Enfin j'ai enlevé le Expect -Header. Mais ça n'a pas aidé. Des idées? J'activé le CookieContainer en réglant

request.CookieContainer = new CookieContainer(); 

Mais je ne vois pas les cookies en-tête HTTP dans la trace. Pourquoi?

+0

Si la première trace HTTP est correcte (pas victime de formatage dans ce post), je ne peux pas voir le corps HTTP que vous envoyez. 'Content-Length' est réglé sur 111 mais je ne vois que le "http/1.1 100 Continue" qui serait la réponse, il me manque le contenu 'data'. Dans la deuxième trace HTTP, je ne vois que 'authentication_token', alors que dans votre code vous utilisez 3 variables. Le code 422 indiquerait «l'échappement incorrect du contenu du corps». C'est probablement en essayant de lire l'une des variables en tant qu'entités. Toute chance que vous avez un ';' caractère PAS échappé dans les chaînes? –

+0

Je viens d'échapper les chaînes contenues dans mes variables en utilisant HttpUtility.UrlEncode(). Mais toujours pas de succès. – Simon

Répondre

4

Ok, je l'ai eu les gars.

J'ai eu deux problèmes.

  1. HTTP 1.1/100ème continuer

    Je résolu ce problème en fixant

  2. Le serveur repsonded avec 422 en raison d'un problème lié aux cookies. La requête POST doit transmettre un conteneur de cookies, que contient un cookie avec l'ID de session en cours. Si cet ID de session est non transmis, le serveur répondra avec 422. Afin de pouvoir avoir un cookie avec l'identifiant de session, j'ai dû effectuer une simple requête HTTP sur la page de connexion. Cette requête a renvoyé un cookie contenant l'identifiant de session requis. Puis j'ai passé le conteneur de cookie retourné à la demande POST.

    //cookie container of previous request 
    postRequest.CookieContainer = cookieContainer; 
    

Avec ce paramètre la requête POST pourrait être envoyé avec succès.

Merci pour votre aide.

1

Vous ne semblez pas échapper le = et @ correctement. Je ne sais pas si c'est le seul problème.

Vous pouvez essayer HttpUtility.UrlEncode.

+0

Comment puis-je effectuer un encodage d'URL dans .NET? – Simon

+0

Merci ... mais toujours pas de succès :( – Simon

+0

@Simon, gardez votre code et la sortie mis à jour. –