redirect 301 для SEO в Nginx

Thank you for reading this post, don't forget to subscribe!

Допу­стим, у вас настро­ен реди­рект с http на https и добав­ле­ние к урлу в кон­це слеш. То есть вы хоти­те такое преобразование:

Допу­стим, у вас сна­ча­ла был настро­ен реди­рект на https подоб­ным образом:

[codesyntax lang="php"]

[/codesyntax]

А потом вас попро­си­ли доба­вить реди­рект всех урлов без сле­ша на тот же урл толь­ко со сле­шем на кон­це. Вы иде­те в сек­цию c listen 443 и добав­ля­е­те редирект.

[codesyntax lang="php"]

[/codesyntax]

В целом все нор­маль­но, реди­рек­ты рабо­та­ют. Но если перей­ти по ссыл­ке http://site.ru/catalog, мы полу­чим 2 301-х редиректа.

[codesyntax lang="php"]

[/codesyntax]

На выхо­де у вас 2 реди­рек­та вме­сто одно­го, что пло­хо для СЕО. Надо по воз­мож­но­сти все реа­ли­зо­вать в одном. В дан­ном слу­чае напра­ши­ва­ет­ся про­стое и оче­вид­ное решение:

[codesyntax lang="php"]

[/codesyntax]

Вро­де бы все нор­маль­но. Теперь реди­рект будет авто­ма­ти­че­ски добав­лять слеш в конец запро­са. Но про­бле­мы нач­нут­ся со ссыл­ка­ми на медиа фай­лы. Напри­мер, запрос http://site.ru/catalog/img.png будет пре­вра­щать­ся в https://site.ru/catalog/img.png/, что нам совер­шен­но не нуж­но. Что­бы это испра­вить, надо сде­лать так.

[codesyntax lang="php"]

[/codesyntax]

Теперь все будет нор­маль­но, так как location со ста­ти­кой ука­зан в виде регу­ляр­но­го выра­же­ния. В слу­чае попа­да­ния запро­са в ука­зан­ное пра­ви­ло, будет выпол­нен реди­рект без сле­ша. Все осталь­ное попа­дет в сле­ду­ю­щий пре­фикс­ный location /. То же самое мож­но сде­лать с помо­щью if и одно­го location, но c if рабо­тать будет мед­лен­нее. Там где мож­но обхо­дить­ся без if, луч­ше его не использовать.

Пример с nginx rewrite

Теперь дру­гая про­бле­ма. Возь­мем такой url - http://site.ru/catalog/. В теку­щем кон­фи­ге он пре­вра­ща­ет­ся в  https://site.ru/catalog//. Исправ­ля­ем это:

[codesyntax lang="php"]

[/codesyntax]

Я исполь­зую rewrite без како­го-либо фла­га на кон­це, что­бы не пре­кра­щать обра­бот­ку дирек­тив. В дан­ном слу­чае про­сто меня­ет­ся uri и пере­да­ет­ся даль­ше. Если запрос при­хо­дит со сле­шом на кон­це, мы его обре­за­ем и отправ­ля­ем в пра­ви­ло реди­рек­та на https. Если сле­ша нет, то он сра­зу на реди­рект ухо­дит. Теперь все в порядке.

 

Встроенные редиректы WordPress

Напри­мер, вы сами не настра­и­ва­ли реди­рект урлов без сле­ша на урлы со сле­шом, он вам не нужен. Но, к при­ме­ру, WordPress реа­ли­зу­ет подоб­ный реди­рект сво­и­ми сред­ства­ми. В ито­ге, при запро­се http://site.ru/catalog вы полу­чи­те такую кар­ти­ну с редиректами.

[codesyntax lang="php"]

[/codesyntax]

Сна­ча­ла nginx сде­лал реди­рект на https, так как вы это настро­и­ли у него в кон­фи­гу­ра­ции, а потом wordpress на стра­ни­цу со сле­шом на кон­це. В ито­ге у вас два реди­рек­та, а надо один. При­чем, два реди­рек­та полу­чи­лись не по вашей воле. Если не обра­ти­те на это вни­ма­ние, так и буде­те с ними жить. По фак­ту, все типо­вые реди­рек­ты луч­ше сра­зу реа­ли­зо­вы­вать в одном месте в веб сервере.

Все стандартные редиректы в nginx

Рас­смот­рю типо­вой при­мер, когда у нас одно­вре­мен­но при­сут­ству­ют сле­ду­ю­щие редиректы:

  1. С http на https.
  2. С www на без www для обо­их протоколов.
  3. Без сле­ша на кон­це на урл со слешем.

Наша цель будет реа­ли­зо­вать все пре­об­ра­зо­ва­ния url в одном месте и выдать кли­ен­ту толь­ко один 301-й редирект.

[codesyntax lang="php"]

[/codesyntax]

Полу­чи­лось при­мер­но так. На выхо­де все­гда один 301 реди­рект, какой бы запрос мы не сде­ла­ли. При этом все реа­ли­зо­ва­но сред­ства­ми само­го веб сер­ве­ра, а зна­чит, будет рабо­тать мак­си­маль­но быстро.

 

Корректный редирект с одного url на другой

Допу­стим вы кор­рект­но настро­и­ли стан­дарт­ные реди­рек­ты в nginx. А потом в какой-то момент у вас поме­ня­лась струк­ту­ра сай­та, или про­сто нуж­но было сде­лать реди­рек­ты для отдель­ных стра­ниц. К при­ме­ру, запрос https://site.ru/main/hello/ пере­на­пра­вить в https://site.ru/main/. По идее ниче­го слож­но­го. Добав­ля­ем редирект:

[codesyntax lang="php"]

[/codesyntax]

Если делать запро­сы по https, то все в поряд­ке. Ника­ких про­блем, сра­бо­та­ет ров­но один 301-й реди­рект на дру­гой url. А что будет при запро­се http://site.ru/main/hello ? Смотрим

[codesyntax lang="php"]

[/codesyntax]

Опять два 301-х реди­рек­та. Пере­де­лы­ва­ем на один, не забы­вая все воз­мож­ные вари­ан­ты написания.

[codesyntax lang="php"]

[/codesyntax]