1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
|
---
title: Перенаправления в HTTP
slug: Web/HTTP/Redirections
tags:
- HTTP
- Начинающий
- Руководство
translation_of: Web/HTTP/Redirections
---
<div>{{HTTPSidebar}}</div>
<p class="summary">URL перенаправление (redirecting), также известное как URL пересылка (forwarding), это метод представления страницы, формы или целого веб-приложения, более чем одним URL адресом. HTTP предоставляет специальный вид ответов, <em><strong>HTTP redirect</strong></em>, для выполнения этой операции, используемой для многих целей: временного перенаправления, пока выполняется обслуживание сайта, постоянное перенаправление, для сохранения работоспособности внешних ссылок, после смены архитектуры сайта, страниц прогресса, пока загружается файл, и так далее.</p>
<h2 id="Принцип_работы">Принцип работы</h2>
<p>В HTTP, перенаправление вызывается при отправке сервером специального ответа на запрос: redirects. HTTP перенаправление, это ответы с кодом статуса<code>3xx</code>. Когда браузер получает ответ перенаправления, он использует новый предоставленный URL-адрес и немедленно загружает его: в большинстве случаев переадресация невидима для пользователя, за исключением небольшого влияния производительность.</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/13785/HTTPRedirect.png"></p>
<p>Есть несколько типов перенаправлений и делятся на три категории: постоянные, временные и специальные перенаправления.</p>
<h3 id="Постоянные_перенаправления">Постоянные перенаправления</h3>
<p>Эти перенаправления призваны длиться вечно. Они подразумевают, что оригинальный URL-адрес больше не должен использоваться, а вместо него должен быть использован новый. Поисковые роботы запускают обновление связанного URL-адреса для ресурса в своих индексах.</p>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Код</th>
<th scope="col">Текст</th>
<th scope="col">Обработка метода</th>
<th scope="col">Случаи использования</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>301</code></td>
<td><code>Moved Permanently</code></td>
<td>{{HTTPMethod("GET")}} методы неизменны.<br>
Другие методы могут быть превращены в {{HTTPMethod("GET")}}.<sup><a href="#attr1">[1]</a></sup></td>
<td>Реорганизация веб-сайта.</td>
</tr>
<tr>
<td><code>308</code></td>
<td><code>Permanent Redirect</code></td>
<td>Метод и тело запроса неизменны.</td>
<td>Реорганизация веб-сайта, с не-GET ссылками/операциями.</td>
</tr>
</tbody>
</table>
<p><a id="attr1" name="attr1"></a>[1] Спецификация не была намерена разрешать изменение метода, но на практике, клиентские приложения делают это. Код <code>308</code> был создан чтобы избавиться от неоднозначности в поведении, при использовании не-<code>GET</code> методов.</p>
<h3 id="Временные_перенаправления">Временные перенаправления</h3>
<p>Иногда, доступ к запрашиваемому ресурсу не может быть предоставлен из определённого места, но может быть предоставлен из другого. В этом случае, могут быть использованы временные перенаправления. Поисковые роботы не запоминают новую, временную ссылку. Временные перенаправления также используются, когда создаются, обновляются, или удаляются ресурсы, которые представляют временные страницы.</p>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Код</th>
<th scope="col">Текст</th>
<th scope="col">Обработка метода</th>
<th scope="col">Случаи использования</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>302</code></td>
<td><code>Found</code></td>
<td>{{HTTPMethod("GET")}} методы неизменны.<br>
Другие методы <u>могут</u> быть превращены в {{HTTPMethod("GET")}}.<sup><a href="#attr2">[2]</a></sup></td>
<td>Веб-страница недоступна по непредвиденным причинам. В этом случае поисковые роботы не будут обновлять свои ссылки.</td>
</tr>
<tr>
<td><code>303</code></td>
<td><code>See Other</code></td>
<td>{{HTTPMethod("GET")}} методы неизменны.<br>
Другие превращены в <code>GET</code> (тело запроса теряется).</td>
<td>Используется для перенаправления после {{HTTPMethod("PUT")}} или {{HTTPMethod("POST")}} для предотвращения обновления страницы, что может спровоцировать повторный вызов операции.</td>
</tr>
<tr>
<td><code>307</code></td>
<td><code>Temporary Redirect</code></td>
<td>Метод и тело запроса неизменны.</td>
<td>Веб-страница недоступна по непредвиденным причинам. В этом случае поисковые роботы не будут обновлять свои ссылки. Лучше чем код <code>302</code> когда не-GET ссылки/операции доступны на сайте.</td>
</tr>
</tbody>
</table>
<p><a id="attr2" name="attr2"></a>[2] Спецификация не была намерена разрешать изменение метода, но на практике, клиентские приложения делают это. Код <code>307</code> был создан чтобы избавиться от неоднозначности в поведении, при использовании не-<code>GET</code> методов.</p>
<h3 id="Специальные_перенаправления">Специальные перенаправления</h3>
<p>В добавок к обычным перенаправлениям, есть 2 специальные. Перенаправление с кодом {{HTTPStatus("304")}} (Not Modified) перенаправляет страницу к локальной закешированной копии (которая была устаревшей), и перенаправление с кодом {{HTTPStatus("300")}} (Multiple Choice) это ручное перенаправление: тело, представленное браузером, как веб-страница, перечисляет возможные перенаправления и пользователь выбирает одно из них.</p>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Код</th>
<th scope="col">Текст</th>
<th scope="col">Случаи использования</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>300</code></td>
<td><code>Multiple Choice</code></td>
<td>Не так много: варианты перечислены на HTML странице. Может быть обслужен со статусом {{HTTPStatus("200")}} <code>OK</code>.</td>
</tr>
<tr>
<td><code>304</code></td>
<td><code>Not Modified</code></td>
<td>Обновление кеша: означает, что значение кеша все ещё актуально и может быть использовано.</td>
</tr>
</tbody>
</table>
<h2 id="Альтернативные_способы_указания_перенаправлений">Альтернативные способы указания перенаправлений</h2>
<p>HTTP перенаправления это не единственный способ переадресации. Есть ещё два метода: HTML перенаправления используют элемент {{HTMLElement("meta")}} , и JavaScript перенаправления используют <a href="/en-US/docs/Web/API/Document_Object_Model">DOM</a>.</p>
<h3 id="HTML_перенаправления">HTML перенаправления</h3>
<p>HTTP перенаправления более предпочтительный способ создания перенаправлений, но, иногда, у веб-разработчиков нету контроля над сервером или возможности настроить его. Для таких особых случаев, разработчики могут создать HTML страницу с элементом {{HTMLElement("meta")}} и установить атрибуту {{htmlattrxref("http-equiv", "meta")}} значение <code>refresh</code> в блоке {{HTMLElement("head")}}. Когда страница отображается, браузер найдёт этот элемент и перейдёт на указанную страницу.</p>
<pre class="brush: html"><head>
<meta http-equiv="refresh" content="0; URL=http://www.example.com/" />
</head>
</pre>
<p>Атрибут {{htmlattrxref("content")}} начинается с числа, которое означает, сколько секунд браузер должен ждать, прежде чем перейти по данной ссылке. Всегда устанавливайте 0, для лучшей доступности.</p>
<p>Очевидно, этот метод работает только с HTML страницами и не может использоваться для изображений или другого типа контента.</p>
<div class="note">
<p><strong>Заметьте</strong>, что перенаправления не позволяют работать должным образом кнопке "Назад" в браузере: вы можете вернуться на страницу назад, но мгновенно будете перенаправлены на страницу с которой пришли.</p>
</div>
<h3 id="JavaScript_перенаправления">JavaScript перенаправления</h3>
<p>Перенаправления в JavaScript создаются установкой значения свойства {{domxref("window.location")}} и новая страница загрузиться.</p>
<pre class="brush: js">window.location = "http://www.example.com/";</pre>
<p>Как и HTML перенаправления, этот тип не будет работать на всех ресурсах, и очевидно, что работает только на стороне клиента, который выполнит JavaScript. С другой стороны, вы можете вызвать перенаправление, только тогда, когда исполнится определённое условие.</p>
<h3 id="Приоритетность">Приоритетность</h3>
<p>При использовании трёх возможных способов URL перенаправления, некоторые методы могут быть вызваны одновременно, но какой из них будет примёнён первым? Порядок приоритетов следующий:</p>
<ol>
<li>HTTP перенаправления всегда выполняются первыми, пока ещё страница даже не была передана, и конечно же, пока ещё не прочитана.</li>
<li>HTML перенаправления ({{HTMLElement("meta")}}) выполняются только, если перенаправление не было в выполнено в HTTP.</li>
<li>JavaScript перенаправления используются как последняя возможность перенаправления, и работают только если разрешено выполнение JavaScript на клиентской стороне.</li>
</ol>
<p>Используйте HTTP перенаправления, когда это возможно, и не используйте элемент {{HTMLElement("meta")}}. Если разработчик изменяет HTTP перенаправление и забывает изменить HTML перенаправление , тогда они больше не идентичны, и закончится это вечным циклом или другим ночным кошмаром.</p>
<h2 id="Случаи_использования">Случаи использования</h2>
<p>Есть много случаев для использования перенаправлений, но поскольку они влияют на производительность, то должны использоваться как можно реже.</p>
<h3 id="Связывание_доменов">Связывание доменов</h3>
<p>В идеале, есть только одно место, и следовательно один URL адрес, для одного ресурса. Но, есть несколько причин, чтобы иметь альтернативные имена для ресурса (несколько доменов, как с, так и без префикса <em>www </em>или более короткие и лёгкие для запоминания адреса, …). В этих случаях, использовать перенаправление к одному истинному URL адресу, более подходящий вариант, чем дублировать ресурс.</p>
<p>Связывание доменов может быть необходимым по нескольким причинам:</p>
<ul>
<li>Расширение вашего сайта. Распространённый случай, когда ваш сайт находится под доменом <code>www.example.com</code> , а доступ к страницам должен быть возможным также из <code>example.com</code> . В этом случае создаются перенаправления для страниц из <code>example.com</code> к страницам <code>www.example.com</code>. Вы также можете предоставлять обычно используемые имена синонимов или частые опечатки ваших доменных имён.</li>
<li>Переезд на другой домен. К примеру, ваша компания была переименована и вы хотите чтобы люди которые обычно использовали старый сайт компании находили вас под новым именем.</li>
<li>Принуждённый HTTPS. Запросы к HTTP версии вашего сайта буду перенаправлены к HTTPS версии.</li>
</ul>
<h3 id="Сохранения_ссылок_рабочими">Сохранения ссылок рабочими</h3>
<p>Когда вы изменяете структуру веб-сайта, URL адреса ресурсов меняются. Даже, если вы можете обновить внутренние ссылки вашего сайта в соответствии с новой схемой имён, у вас нет контроля на URL адресами используемыми внешними ресурсами. Вы не хотите, чтобы эти ссылки не работали, так как они приносят вам ценных пользователей (и помогают вашей SEO), так что вы устанавливаете перенаправления из старых URL адресов на новые.</p>
<div class="note">
<p>Не смотря на то, что данный метод работает также для внутренних ссылок, вы должны избегать внутренних перенаправлений. Перенаправления имеют большое влияние на производительность, и если вы имеете возможность избежать их, корректируя внутренние ссылки, тогда делайте так.</p>
</div>
<h3 id="Временные_ответы_для_небезопасных_запросов">Временные ответы для небезопасных запросов</h3>
<p>{{Glossary("safe", "Небезопасные")}} запросы изменяют состояние сервера и пользователь не должен не нарочно запросить их. Обычно, вы не хотите чтобы ваши пользователи повторно отправляли {{HTTPMethod("PUT")}}, {{HTTPMethod("POST")}} или {{HTTPMethod("DELETE")}} запросы. Если вы только обслуживаете запросы, простое нажатие кнопки перезагрузки повторно отправит запрос. </p>
<p>В этом случае, сервер вернёт ответ {{HTTPStatus("303")}} (Смотреть другие), который будет содержать правильную информацию, но если кнопка перезагрузки будет нажата, эта страница просто отобразится повторно без ответа на небезопасный запрос.</p>
<h3 id="Временные_ответы_на_долгие_запросы">Временные ответы на долгие запросы</h3>
<p>Некоторые запросы могут потребовать больше времени сервера, например запрос {{HTTPHeader("DELETE")}}, который срабатывает по расписанию. В этом случае, ответом будет перенаправление {{HTTPStatus("303")}} (Смотреть другие), которое связывает со страницей показывающей, что действие было запланировано, и в результате информирует о процессе или позволяет отменить запрос.</p>
<h2 id="Настройка_перенаправлений_на_распространённых_серверах">Настройка перенаправлений на распространённых серверах</h2>
<h3 id="Apache">Apache</h3>
<p>Перенаправления могут быть установлены или в настройках сервера, или в каждой директории в файле <code>.htaccess</code>.</p>
<p>У модуля <a href="https://httpd.apache.org/docs/current/mod/mod_alias.html">mod_alias</a> есть директивы <code>Redirect</code> и <code>Redirect_Match</code> которые, по умолчанию, устанавливают код ответа {{HTTPStatus("302")}}:</p>
<pre><VirtualHost *:80>
ServerName example.com
Redirect / http://www.example.com
</VirtualHost>
</pre>
<p>URL <code>http://example.com/</code> будет перенаправлен к <code>http://www.example.com/</code> (но не к <code>http://example.com/other.html</code> )</p>
<p><code>Redirect_Match</code> делает то же, но использует регулярное выражение, чтобы определить множество URL адресов, которые подпадут под эффект:</p>
<pre>RedirectMatch ^/images/(.*)$ http://images.example.com/$1</pre>
<p>Все документы в папке <code>images/</code> будут перенаправляться к другому домену.</p>
<p>Если вы не хотите устанавливать временное перенаправление, дополнительный параметр (используйте или код статуса HTTP, или ключевое слово <code>permanent) </code>может использоваться чтобы установить другое перенаправление:</p>
<pre>Redirect permanent / http://www.example.com
Redirect 301 / http://www.example.com
</pre>
<p>Также модуль <a href="http://httpd.apache.org/docs/current/mod/mod_rewrite.html">mod_rewrite</a> может использоваться для создания перенаправлений. Они более гибкие, но сложнее в использовании.</p>
<h3 id="Nginx">Nginx</h3>
<p>В Nginx, вы создаёте особый серверный блок для контента, который вы хотите перенаправлять:</p>
<pre>server {
listen 80;
server_name example.com;
return 301 $scheme://www.example.com$request_uri;
}</pre>
<p>Чтобы применить перенаправления к папке или подмножеству страниц, используйте директиву <code>rewrite</code>:</p>
<pre>rewrite ^/images/(.*)$ http://images.example.com/$1 redirect;
rewrite ^/images/(.*)$ http://images.example.com/$1 permanent;
</pre>
<h3 id="IIS">IIS</h3>
<p>В IIS, вы используете элемент <code><a href="https://www.iis.net/configreference/system.webserver/httpredirect"><httpRedirect></a></code> для настройки перенаправлений.</p>
<h2 id="Циклы_перенаправлений">Циклы перенаправлений</h2>
<p>Циклы перенаправлений случаются когда за успешным перенаправлением следует другое, которое уже было выполнено. Другими словами, существует такой цикл, который никогда не закончится и в конечном счёте ни одна страница не будет найдена.</p>
<p>В большинстве случаев это проблема сервера, и если сервер не может обнаружить её, то отправит код статуса {{HTTPStatus("500")}} <code>Internal Server Error</code>. Если вы встретите такую ошибку вскоре после редактирования настроек сервера, то это скорее всего цикл перенаправлений.</p>
<p>В случае, когда сервер не может обнаружить его: цикл перенаправлений может распространиться на несколько серверов, каждый из которых не имеет полной картины происходящего. В этом случае, браузеры покажут сообщение об ошибке. Firefox выведет:</p>
<pre class="bz_comment_text" id="comment_text_0">Firefox has detected that the server is redirecting the request for this address in a way that will never complete.</pre>
<p>тогда, как Chrome:</p>
<pre>This Webpage has a redirect loop</pre>
<p>В обоих случаях, пользователь не может ничего сделать (в отличие от ошибки на стороне клиента, например, несоответствие файлов куки или кеша).</p>
<p>Важно избегать циклов перенаправлений, так как они полностью нарушают работу пользователя.</p>
|