Отправляет email-рассылки с помощью сервиса Sendsay

.NET: Записки программиста

  Все выпуски  

URL rewriting в ASP.NET для поисковой оптимизации (SEO)



URL rewriting в ASP.NET для поисковой оптимизации (SEO)

SEO Url rewriting Если вы попали на эту страницу с поискового сервера - вам не нужно объяснять зачения этих слов. Cтатья поможет вам упорядочить картину "URL rewriting, что и как я могу сделать", а так же понять, что находится в арсенале разработчика ASP.NET, плюсы и минусы основных решений.

Если же вы получили эту статью в рассылке или зашли сюда по старой памяти, давайте взглянем на слова "SEO, user and serach engine friendly urls, improving the search relevancy, protect site content". Если выражение вашего лица стало хоть чуть более заинтересованным - наливаем кофе, устраиваемся поудобнее и читаем дальше.

Для того, чтобы уйти от общих фраз, давайте сразу представим себе реальный пример: скажем, владелец домена news.ru заказал у вас разработку новостного портала. И как у нас водится - это должен быть портал всех порталов, убийца остальных новостных ресурсов и т.д. Он будет содержать десятки тысяч новостей, разбитых по категориям и темам и, естественно, должен быть вооружен последними достижениями SEO, чтобы максимально ускорить вожделенный и столь горячо обсуждаемый процесс "монетаризации".

Что нам может понадобится?

  1. Вынести категории новостей в отдельные поддомены, например fashion.news.ru, sport.news.ru, movies.news.ru и т.п.

  2. Использовать user friendly (т.е. интуитивно понятные пользователю) urls, например:
    • http://sport.news.ru/ukraine/dinamo-kiev/2007 - новости о киевском клубе "Динамо" за 2007 год
    • http://moviesnews.ru/comedy/france/top - самые популярные новости о французских комедиях

  3. Использовать статические urls, включающие ключевые слова вместо динамических страниц с параметрами, например:
    http://sex.news.ru/topmodels/dima-bilan-with-famous-top-model
    вместо
    http://sex.news.ru/list.aspx?rubric=topmodels&articleId=5624
    Тут разница в прямом смысле бросается в глаза.

  4. Если на какую-то страницу можно попасть, используя несколько url - оставить только один и делать на него редиректы со всех остальных вариантов (чтобы не распылять рейтинг). Например, если у нас есть главная страница поддомена sport.news.ru "main.aspx", оставить ей url http://sport.news.ru, делая 301 (permanent) редирект с остальных вариантов, типа:
    http://sport.news.ru/main.aspx
    http://www.sport.news.ru
    http://www.sport.news.ru/main.aspx
    http://sport.news.ru/Main.aspx (Google различает регистр части url, идущей после доменного имени, так что Main.aspx и main.aspx для него две совершенно разные страницы).
Прим. Если вы задумались, действительно ли такие перенаправления могут сильно повлиять на рейтинг вашего сайта, у Джона Херда есть хорошая статья по этому поводу - How URLs Can Affect Top Search Engine Rankings.

Теперь подумаем, при помощи чего мы все это сможем сделать. Кто сказал "чего тут думать, тут гуглить нужно"? :) Хорошо, давайте попробуем. Набраем ключевые слова "url rewriting asp.net" и ... когда-нибудь, я надеюсь, мы найдем ссылку на эту статью (интересно, кто-нибудь из программистов-педантов уйдет в бесконечный цикл? :), но пока давайте немного помечтаем, и представим себе, что бы нам выдала абсолютно релевантная машина. Только будем рассматривать ссылки в обратном порядке, от самых примитивных, к самым функциональным, хорошо?

Итак, самая нижняя ссылка результатов запроса

URL Mapping in ASP.NET 2.0


Самый простой вариант с минимумом возможностей. Вы просто добавляете в <web.config> секцию с парами url "откуда перенаправлять" - "куда перенаправлять". Возможны только статические urls, никаких шаблонов, а тем более регулярных выражений. Пригодиться это может только в простейших случаях. Например, начитавшись статей по SEO, вы захотите переименовать статью на вашем сайте из "Article28.aspx" в "TenTopSeoRules.aspx". Чтобы не потерялись закешированные поисковиками и сохраненные пользователями ссылки, вы можете добавить в <web.config> такие строки:

<configuration>
  <system.web>
    <urlMappings enabled="true">
        <add url="~/Article28.aspx" mappedUrl="~/TenTopSeoRules.aspx"/>
    </urlMappings>
  </system.web>
</configuration>

Как-то у Scott Guthrie1 спросили, почему URL Mapping не поддерживает регулярные выражения. Он ответил, что как раз в это время они разрабатывали IIS 7.0 и решили, что в защищенном и масштабируемом решении было бы неплохо использовать новые мощные возможности новой версии IIS - так что более богатую функциональность они просто отложили до какой-нибудь будущей версии.

Более подробно (если там вобще есть о чем читать) о URL Mapping вы можете посмотреть в ASP.NET Quickstart Tutorials.

Но, в любом случае, ничего из того, что нам нужно, он нам предложить не сможет.

Продолжаем продвигаться по нашему списку ссылок вверх. Следующий вариант

RemapUrl из IIS 6.0 Resource Kit


Эта утилита входит в состав IIS 6.0 Resource Kit. и является не частью ASP.NET, как предыдущий вариант, а ISAPI модулем для IIS. Возможности ее также очень ограничены, она может всего три вещи:
  1. Статически перенаправлять одни urls на другие, в пределах одного и того же приложения. Причем, насколько я понял, шаблонов, а тем более регулярных выражений, она так же не поддерживает (чуствуется дух Scott Guthrie? :).

  2. Так же статически перенаправлять urls на urls других приложений, в этом случае url, на которые идет перенаправление нужно задавать абсолютно, начиная с http://.

  3. И, наконец-то, третий вариант, который не поддерживается стандартным ASP.NET mapping - вы можете указать, что при запросе определенного url нужно возвращать некоторый код ошибки. Для этого используется формат "/url=xxx,y,desc", где xxx - это http статус, y - вспомогательный код ошибки (suberror), а desc - текст сообщения об ошибке.
Сама утилита состоит из двух файлов, RemapUrl.dll, который нужно зарегистрировать как ISAPI модуль под IIS и конфигурационного файла RemapUrl.ini. В посте RemapURL -Complete Instructions? можно прочитать подробнее, как нужно подключать RemapUrl.dll, а ниже приведен пример конфигурационного файла (символы ";" используются в нем для выделения комментариев).

[Mappings]
; - Local mapping
/URL1=/Some-Other-URL

; - Redirect mapping
/URL2=http://www.microsoft.com

; - Error mapping
/URL3=500,13,Server Too Busy

Для наших целей его возможностей явно не хватает, так что мы переходим к следующей ссылке.

Custom rewriting in ASP.NET


К сожалению, это не название какой-то технологии или библиотеки. Это всего-то значит, что url rewriting мы можем реализовать и сами. Сразу хочу вас успокоить, есть несколько библиотек, которые реализуют эту идею, их мы рассмотрим ниже. Но, во-первых, всегда лучше знать, по какому принципу что-то работает (помните, "знание общих принципов заменяет незнание отдельных фактов"), а во-вторых, часто для счастья нужно совсем чуть-чуть, но вот этого чуть библиотека и не позволяет. Так что посмотрим, как можно реализовать rewriting своими руками.

Для того, чтобы это понять, нам прийдется освежить в памяти порядок, в котором сервер обрабатывает http запросы. Честно признаться, мне было лень рисовать подробную картинку, так что я просто позаимствовал вот эту, а пару недостающих моментов мы дорисуем при помощи нашей фантазии, идет?

IIS ASP request workflow
Рис. 1

Давайте вспомним наш пример. Допустим, пользователь набирает в строке запроса браузера url http://sport.news.ru/ukraine/dinamo-kiev/:
  1. Браузер обращается к DNS серверу и выясняет, что компьютер, который поддерживает доменное имя sport.news.ru имеет такой-то IP (организация, у которой заказчик во время золотой лихорадки urls успел захватить домен news.ru, должна позаботиться, чтобы это был IP именно нашего компьютера :).

  2. Запрос попадает к IIS на нашем сервере. Тот просматривает сконфигурированные на нем сайты и ищет тот, с которым в настройках связанно доменное имя sport.news.ru. Диалог, в котором можно задать такую связь, вызывается из оснастски IIS и выглядит так:

    Web site identification
    Рис. 2

    Если соответствия не найдено, запрос передается сайту, помеченному как default.

  3. А вот теперь нам пригодится немного фантазии. Посмотрите на рис.1. Блок, изображающий IIS, пустой, зато на блоке с ASP.NET engine запрос последовательно проходит через HTTP Modules и HTTP Handlers. Теперь мысленно копируем изображение на блоке ASP.NET engine и накладываем его на блок IIS. Дело в том, что обработка запросов как IIS, так и ASP.NET очень похожа. Сначала запрос проходит некоторое количество фильтров (если они заданы). Пропуская запрос через себя, фильтр может каким-то образом его изменить или выполнить другую полезную работу (логирование, аутентификация, проверка прав). Потом запрос попадает к обработчику (handler), который и должен сформировать ответ, который IIS отошлет браузеру обратно.

    Чтобы не запутаться, обратите внимание, что фильтры для IIS называются ISAPI Filters, а для ASP.NET - Http Modules. Обработчики для IIS называются ISAPI Extensions (или ISAPI Applications), а для ASP.NET - Http Handlers. Кроме того, до появления IIS 7.0, который входит в состав Windows Vista (уже выпущена) и в Windows Server 2008 (запуск которой назначен на 27 февраля 2008 в Лос Анджелесе), модули под IIS приходилось писать на unmanaged C++, а вот для ASP.NET мы, естественно, можем использовать любой из .NET совместимых языков.

    Итак, вернемся к нашему запросу. Вначале, он проходит через ISAPI Filters, указанные для web-сайта (кроме того, можно задать фильтры, которые будут использоваться для всех сайтов, созданных под IIS). Фильтры можно указывать на закладке "ISAPI Filters" диалога "Website Properties". Он приведен на рис. 3.

    ISAPI Filters
    Рис. 3

    ISAPI filters будут вызываться именно в том порядке, в котором они были указаны на закладке.

  4. После этого, наступает очередь "wildcard application mappings". Эта возможность появилась в IIS 6.0. Она позволяет указать ISAPI Applications, которые будут выполняться для любых запросов, вне зависимости от типа расширения. Вести они себя должны как ISAPI filters (т.е. пропускать через себя запросы, возможно подправляя их или выполняя какую-нибудь другую полезную работу. При этом, как полноценные ISAPI Applications, они обладают большими чем фильтры возможностями, например имеют доступ не только к заголовку, но и к телу запроса.

    Задать эти модули можно на закладке "Application configuration" (диалог "Website properties" -> закладка "Home Directory" -> кнопка "Configuration" -> диалог "Application Configuration" -> секция "Wildcard application mapps"). Она приведена на рис. 4.

    Wildcard application mappings
    Рис. 4

    ISAPI Applications будут вызываться в том же порядке, в котором они были указаны на закладке.

  5. После этого, в зависимости от типа файла, IIS выбирает, какому из ISAPI Extensions (Applications) нужно передать управление. Привязки типов файлов (т.е. расширений) к ISAPI Extensions можно задать на закладке "Mappings" (диалог "Website Properties" -> закладка "Home Directory" -> кнопка "Configuration" -> диалог "Application Configuration" -> закладка "Mappings"). Эта закладка показана на рис. 5.

    ISAPI Extensions Mapping
    Рис. 5

    Так, выбранная нами запись показывает, что запросы к файлам с расширением .aspx нужно передавать на обработку ISAPI Extension aspnet_isapi.dll.

  1. Итак, IIS передает ход ISAPI Application aspnet_isapi.dll, а тот, в свою очередь, перенаправляет запрос процессу w3wp.exe (для Windows 2003) или aspnet_wp.exe (если у вас Windows XP), которые и являются движками, для выполнения ASP.NET прилолжений.

  2. Здесь картина опять повторяется. Сначала ASP.NET по очереди вызывает все модули (HttpModules), зарегистрированные для web-приложения. Для этого просматриваются секции <httpModules> всех конфигурационных файлов, начиная от корневого machine.config и заканчивая web.config файлом, ближе всех расположенным к вызываемой странице. Именно таким образом вызываются системные модули типа Session (поддерживающий понятие "сессия") или FormsAuthentication (выполняющий аутентификацию пользователей).

    Вот пример из корневого web.config файла, расположенного в каталоге "<windows>\Microsoft.NET\Framework\<version>\config\":
    <configuration>
      <system.web>
        <httpModules>
            <add name="OutputCache" type="System.Web.Caching.OutputCacheModule"/>
            <add name="Session" type="System.Web.SessionState.SessionStateModule"/>
            . . .
        </httpModules>
      </system.web>
    </configuration>

  3. И, наконец-то, ASP.NET ищет тот HttpHandler, который, собственно, и обработает запрос. Для этого опять прсматриваются все конфигурационные файлы, в которых можно сопоставлять модули с запрашиваемыми типами файлов, а так же с типами запросов. Например, можно указать, что HttpHandler "MyAssembly.MyHandler" нужно вызывать, если идет обращение типа "GET" к файлам с расширением .aspx:
    <configuration>
      <system.web>
        <httpHandlers>
          <add path=".aspx" verb="GET" type="MyAssembly.MyHandler"/>
          . . .
        </httpHandlers>
      </system.web>
    </configuration>

    Если пользовательских обработчиков не найдено, в корневом web.config прописаны обработчики по умолчанию, например для .aspx страниц вызывается System.Web.DefaultHttpHandler.

  4. Стандартный ASP.NET обработчик передает управление вашей странице, унаследованной от класса Page. Сформированный страницей ответ (объект HttpResponse) передается по цепочке обратно и, в конце концов, отсылается браузеру, приславшему запрос.
Web Optimization Уф, мои поздравления тем, кто набрался терпения и таки добрался до этого места. Теперь мы знаем вполне достаточно, чтобы легко понять все остальные способы перенаправления urls.


Продолжение следует


1 Scott Guthrie - генеральный менеджер в Microsoft Developer Division. "Скромный" список продуктов, которыми занимаются группы его разработчиков, включает в себя Common Language Runtime, ASP.NET, IIS 7.0, Visual Web Developer и пр.

В избранное