Создание приложений .NET с поддержкой IDN сайтов
- modified:
- reading: 2 minutes
IDN (Internationalized domain name) – это имена доменов, которые могут быть представлены в виде имени, содержащем не только латинские буквы, но и буквы других национальных алфавитов, вроде русского, арабского, китайского и т.п. (на данный момент поддерживается не так много). Представлены – это ключевое слово, так как на самом деле хранятся и передаются они в виде Punycode строк. Например, у нашей любимой почты России есть сайт http://почтароссии.рф, а Punycode представление этого сайта http://xn--80aqavbdjjaf8c.xn--p1ai/. Это важно понимать, если вы будете в запросах своего приложения (используя WebRequest, например) писать хост как IDN представление, то это имя хоста не будет распознано (если у вас не какой-нибудь специальный DNS сервер), нужно заранее переводить его в Punycode строку.
Браузер IE9, например, умеет отображать IDN представления сайтов, и даже с ними работать.
Chrome так же отлично работает с IDN представлениями, но отображает их сразу же в Punycode строках.
Теперь перейдем к .NET, если вы создадите простое консольное приложение, и напишите там такой код:
Uri uri = new Uri("http://почтароссии.рф/");
WebRequest wr = WebRequest.Create(uri);
WebResponse response = wr.GetResponse();
Console.WriteLine(response.ContentLength);
На этапе исполнения GetResponse вы получите ошибку System.Net.WebException: The remote name could not be resolved: 'почтароссии.рф'. Победить это очень легко, нужно всего лишь добавить поддержку IDN сайтов вашему приложению, для этого в файле app.config нужно добавить:
<configuration>
<uri>
<idn enabled="All"/>
</uri>
</configuration>
После этого все будет работать. Почитать подробнее об этих настройках можно, например, на странице MSDN о Uri классе, под заголовком International Resource Identifier Support.
Но что делать, если вы пишите плагины для какого-нибудь приложения, и вы не в силах поменять глобальные параметры приложения, нет доступа, либо авторы не хотят ничего менять и править? Тут возникает сложность, так как эти параметры поддержки интернациональных доменов читаются только один раз, при первом создании объекта типа Uri, дальше изменение этих параметров уже ни на что не влияет.
В таком случае нужно делать самому кодировку IDN сайта в Punycode представление при помощи класса IdnMapping:
IdnMapping idn = new IdnMapping();
Uri uriIdn = new Uri("http://почтароссии.рф/");
UriBuilder uriBuilder = new UriBuilder(uriIdn);
uriBuilder.Host = idn.GetAscii(uriBuilder.Host);
WebRequest wr = WebRequest.Create(uriBuilder.Uri);
WebResponse response = wr.GetResponse();
Console.WriteLine(response.ContentLength);
На данный момент еще не все сервисы и не все приложения понимают IDN имена. Так, например, известный сервис Twitter не распознает ссылки, содержащие IDN имена хостов, во время написания поста (для “укорачивания” ссылки). Вы же будьте готовы ;)