Třída System.Net.HttpWebRequest irituje mnoho svých uživatelů. Mě taky.
Pro testování HTTP serveru (programoval jsem do IIS jakousi extenzi) jsem potřeboval skriptovatelného HTTP klienta, který jednoduše pošle HTTP request (respektive spoustu identických requestů) s nastavenou hlavičkou Authorization a změří jak dlouho trvá čekání na odpověď. Naprogramovat prototyp v .NET šlo docela dobře - HttpWebRequest má property Credentials, které se dá přiřadit instance NetworkCredential (která se inicializuje jménem a heslem), a podpora threadů umožňuje efektivní paralelizaci požadavků bez komplikací meziprocesové komunikace - jenže když jsem to spustil, selhával testovací klient mnohem dřív než testovaný server... První požadavek prošel, ale když jsem se podíval, co server dostává, zjistil jsem, že odpovídá na dva: první bez autorizace (podle konfigurace - dodneška nevím čeho - může také dostat autorizaci Negotiate, obsahující jakási binární data), který je samozřejmě odmítnut, a až potom požadavek, který jsem chtěl poslat. Co hůř, v multithreadovém klientovi neunese HttpWebRequest svou vlastní složitost a pro polovičku requestů vyhodí vyjímku, že prý ho server nechce autorizovat...
Napsal jsem si vlastní kód skládající autorizační header:
StringBuilder sb = new StringBuilder();
sb.Append("Authorization: Basic ");
byte[] cred = new byte[user.Length + 1 + password.Length];
int idx = 0;
for (int i = 0; i < user.Length; ++i)
{
cred[idx++] = (byte)(user[i]);
}
cred[idx++] = (byte)':';
for (int i = 0; i < password.Length; ++i)
{
cred[idx++] = (byte)(password[i]);
}
sb.Append(System.Convert.ToBase64String(cred));
Tak končí vysokoúrovňová rozhraní... A stejně to nepomohlo: klient s tímto kódem sice posílá pouze jeden požadavek, ale multithreading stále selhává (přičemž požadavky z paralelně běžících procesů projdou, takže problém těžko bude na serveru).
Pro marketingový materiál není tak těžké odfajfkovat: .NET má třídy pro internetové protokoly, .NET podporuje multithreading. Implementace bývá problematičtější...