Я не думаю, что это имеет какое-либо отношение к безопасности. Ошибка 500 - это ошибка на стороне сервера. Что-то в запросе, создаваемом XmlReader.Create (url), сбивает с толку веб-сайт ibm. Если это была проблема безопасности, как было предложено в вашем вопросе, тогда вы ожидаете получить ошибку 403 или «Отказ авторизации». Но вы получили 500, что является ошибкой приложения.
Несмотря на это, возможно, что-то может сделать приложение-клиент, чтобы избежать путаницы с сервером.
Я просмотрел заголовки исходящих HTTP-запросов, используя Fiddler. Для запроса генерируемой IE, заголовки выглядят следующим образом:
GET https://www.ibm.com/developerworks/mydeveloperworks/blogs/roller-ui/rendering/feed/gradybooch/entries/rss?lang=en HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, application/x-silverlight-2-b2, */*
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0; .NET CLR 3.5.30729;)
Accept-Encoding: gzip, deflate
Host: www.ibm.com
Connection: Keep-Alive
Cookie: UnicaNIODID=Ww06gyvyPpZ-WPl6K7y; conxnsCookie=en; IBMPOLLCOOKIE=""; UnicaNIODID=QridYHCNf7M-WYM8Usr
Для запроса от XmlReader.Create (URL), заголовки выглядят следующим образом:
GET https://www.ibm.com/developerworks/mydeveloperworks/blogs/roller-ui/rendering/feed/gradybooch/entries/rss?lang=en HTTP/1.1
Host: www.ibm.com
Connection: Keep-Alive
Довольно разница. Кроме того, в ответ на последний я получил заголовок Set-Cookie
в ответе 500, которого нет в ответе на IE.
Основываясь на этом, я предположил, что это была разница в заголовках запросов, в частности, в cookie, что вводило в заблуждение ibm.com.
Я не знаю, как убедить XmlReader.Create(), чтобы вставлять все заголовки запросов, которые я хотел, включая печенье. Но я знаю, как это сделать с помощью HttpWebRequest. Поэтому я использовал это.
Было несколько препятствий, которые я должен был очистить.
Мне нужен постоянный файл cookie для ibm.com. Для этого мне пришлось прибегнуть к p/invoke из Win32 InternetGetCookie. См. Класс PersistentCookies, прикрепленный в содержимом, предоставленном пользователями, в нижней части страницы документа для WebRequest, как это сделать. После прикрепления файла cookie я больше не получал 500 ошибок. Ура!
Но полученный поток не может быть прочитан XmlReader.Create(). Мне это показалось двоичным. Я понял, что мне нужно сжать gzip или сдутый контент. Для этого мне пришлось
обернуть GZipStream или DeflateStream вокруг полученного потока ответов и использовать поток распаковки для XmlReader.
задать объект AutomaticDecompression собственности на HttpWebRequest. Я мог бы избежать необходимости в этом, не включая «gzip, deflate» в заголовке Accept-Encoding
в исходящем запросе. Фактически, после установки свойства AutomaticDecompression эти заголовки задаются неявно в исходящем HTTP-запросе.
Когда я это сделал, я получил фактический текст. Но некоторые из байтовых кодов были отключены.Затем мне нужно было использовать правильную текстовую кодировку в TextReader, как указано в HttpWebResponse.
После этого, я получил толковую строку, но в результате распакованного поток RSS вызвал XmlReader задыхаться, с
ReadElementString method can only be called on elements with simple or empty content. Line 11, position 25.
Я посмотрел и нашел небольшой <script>
блок, в этом месте, в элементе <copyright>
в документе rss. Кажется, IBM пытается заставить браузер «локализовать» дату авторских прав, добавив логику, которая будет работать в браузере для форматирования даты. Кажется, это слишком много для меня, или даже ошибка IBM. Но поскольку угловая скобка внутри текстового узла элемента искала XmlReader, я удалил блок сценария с заменой Regex.
После очистки этих препятствий, он работал. Приложение .NET смогло прочитать поток RSS с этого https-url.
Я не проводил никаких дальнейших испытаний - чтобы увидеть, будет ли изменяться заголовок Accept
, или заголовок Accept-Encoding
изменит поведение. Это вам нужно выяснить, если вам все равно.
Итоговый код приведен ниже. Это намного уродливее, чем ваш простой 3-лайнер. Я не знаю, как сделать это проще.
public void Run()
{
string url;
url = "https://www.ibm.com/developerworks/mydeveloperworks/blogs/roller-ui/rendering/feed/gradybooch/entries/rss?lang=en";
HttpWebRequest hwr = (HttpWebRequest) WebRequest.Create(url);
// attach persistent cookies
hwr.CookieContainer =
PersistentCookies.GetCookieContainerForUrl(url);
hwr.Accept = "text/xml, */*";
hwr.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-us");
hwr.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; .NET CLR 3.5.30729;)";
hwr.KeepAlive = true;
hwr.AutomaticDecompression = DecompressionMethods.Deflate |
DecompressionMethods.GZip;
using (var resp = (HttpWebResponse) hwr.GetResponse())
{
using(Stream s = resp.GetResponseStream())
{
string cs = String.IsNullOrEmpty(resp.CharacterSet) ? "UTF-8" : resp.CharacterSet;
Encoding e = Encoding.GetEncoding(cs);
using (StreamReader sr = new StreamReader(s, e))
{
var allXml = sr.ReadToEnd();
// remove any script blocks - they confuse XmlReader
allXml = Regex.Replace(allXml,
"(.*)<script type='text/javascript'>.+?</script>(.*)",
"$1$2",
RegexOptions.Singleline);
using (XmlReader xmlr = XmlReader.Create(new StringReader(allXml)))
{
var items = from item in SyndicationFeed.Load(xmlr).Items
select item;
}
}
}
}
}
Что такое ошибка сервера? – David
@David, я добавил информацию об ошибке на свое сообщение –
Код, который вы опубликовали, не содержит обращения к WebClient.OpenRead. Можете ли вы показать нам код, создающий исключение? – dtb