Záludná chyba při použití HttpWebRequest objektu z Net 2.0

MyEgo.cz

home foto blogy mywindows.cz kontakt

Záludná chyba při použití HttpWebRequest objektu z Net 2.0

Aneb co dělat s 'The server committed a protocol violation. Section=ResponseStatusLine' chybou

Narazil jsem na problém při komunikaci s webovou službou přes http protokol. Co mě ale na chybě zaráželo, že se objevovala jen při opakovaném volání. Při prvním requestu komunikace proběhla v pořádku a odpověď se zpracovala tak jak má. Při druhém zkolabovalo zpracování odpovědi na výše zmíněnou chybu.

Při googlování jsem většinou narazil na to, že se jedná o chybu zpracování hlavičky requestu. Tato chyba se pak řeší pomocí přidáním (tajného, vlastnost není standardně přístupná v kódu) konfiguračního elementu do config souboru. Viz.

<system.net>
<settings>
<httpWebRequest useUnsafeHeaderParsing = "true"/>
</settings>
</system.net>

 

Avšak řešení mého problému spočívala v jednoduší úpravě. Stačilo nastavit KeepAlive vlastnost Request objektu na false. Viz.

private string HttpPost(string postData)
{
HttpWebRequest httpWebRequest = (HttpWebRequest) WebRequest.Create(_serviceUri);

if (_httpTimeOut > 0)
httpWebRequest.Timeout = _httpTimeOut;
if (_proxy != null)
httpWebRequest.Proxy = _proxy;
if (_webserverCredentialName != null)
httpWebRequest.Credentials = _webserverCredentialName;

httpWebRequest.Method = _method;
httpWebRequest.UserAgent = "Test";
httpWebRequest.ContentType = _content;
httpWebRequest.AllowAutoRedirect = false;
httpWebRequest.ContentLength = postData.Length;
httpWebRequest.KeepAlive = false;
using (StreamWriter myWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
myWriter.Write(postData);
}
using (WebResponse response = httpWebRequest.GetResponse())
{
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
return sr.ReadToEnd();
}
}
}

 

Falešně jsem se domníval, že když použiji using konstrukci, tak dojde k úplnému uzavření spojení a nebude potřeba nastavovat KeepAlive parametr. Avšak člověk míní a život mění.

Jediná věc, která mě napadla, proč to nefungovalo původně bez tohoto nastavení je teorie, že k uzavření dojde až po vypršení timeoutu. Takže pokud jsem chtěl opakovat request, tak to padlo při zpracování, protože nebyl uzavřen předchozí request.


Komentáře

  1. 1 Discogio 11.02.09, 05:02:35
    FB

    Ono hlavně je dobré využívat ještě klauzule try,catch,finally a tradičně ve finally pozavírat vše co je otevřené.

  2. 2 Jaroslav Urban 13.02.09, 03:02:23
    FB

    [1] Odchytávání chyb mám jen globálně a při použití USING se případné otevřené spojení uzavře samo. Takže tohle by mělo být ošetřený ;-)

  3. 3 Tomáš Herceg 13.02.09, 09:02:58
    FB

    [2] Na to, že using zavírá spojení, není nikdy dobré spoléhat. Ten řádek člověka nezabije a ušetří si tím mnoho problémů. Using je hlavně kvůli tomu, aby volalo Dispose, což ale vůbec nemusí mít nic společného s Close (i když při pohledu na implementaci do zdrojáků .NETu většinou má).

Nový komentář