Что случилось с этим перенаправлением 302 на тот же URL-адрес?
Я просматривал свой веб-сайт в поисках ссылок, указывающих на перенаправление HTTP 301/302/303, когда обнаружил загадочное поведение утилиты curl. Рассмотрим выходные данные следующих трех команд:
$ curl -I http://jekyllrb.com
HTTP/1.1 302 Found
Connection: close
Pragma: no-cache
cache-control: no-cache
Location: /
$ curl -I http://jekyllrb.com/
HTTP/1.1 302 Found
Connection: close
Pragma: no-cache
cache-control: no-cache
Location: /
$ curl -LI http://jekyllrb.com/
HTTP/1.1 200 OK
Server: GitHub.com
Date: Tue, 30 Dec 2014 01:31:47 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 8177
Last-Modified: Mon, 22 Dec 2014 14:17:25 GMT
Expires: Tue, 30 Dec 2014 01:41:47 GMT
Cache-Control: max-age=600
Vary: Accept-Encoding
Accept-Ranges: bytes
Я понимаю вывод первой команды: если вы запросите "голый" домен, вы будете перенаправлены на путь "/". Но когда вы на самом деле запрашиваете указанный путь, вы, похоже, перенаправляетесь на только что запрошенный URL-адрес!
Затем, когда вы добавляете -L
возможность указать curl следовать перенаправлениям, это выглядит так, как будто вы переходите непосредственно на реальную страницу без каких-либо промежуточных шагов! (Обычно, когда curl следует перенаправлениям, он печатает набор заголовков для каждого запроса - если бы где-то там был HTTP 302, то он должен был быть показан до HTTP 200.)
Может ли кто-нибудь объяснить мне (1), почему перенаправление на один и тот же URL-адрес допустимо; и (2) почему включение флага -L
, похоже, не следует, а вместо этого полностью обходит перенаправление?
2 answers
Ваши первые два запроса одинаковы. Все клиенты (включая curl) должны отправлять косую черту после имени домена как часть HTTP-запроса, независимо от того, находится ли он в URL-адресе. Без него невозможно сформулировать действительный HTTP-запрос. Минимальный HTTP-запрос:
GET / HTTP/1.0
host: jekyllrb.com
Пропуск косой черты из этого приведет к ошибке "400 неверных запросов".
Похоже, что поведение является прерывистым. Иногда сервер отвечает перенаправлением, а иногда нет. Я сам пробовал это десятки раз с помощью curl и иногда получаю перенаправление, но в большинстве случаев этого не происходит.
Перенаправление на один и тот же URL-адрес иногда используется для установки файлов cookie и проверки их установки. Я не вижу, чтобы в этом запросе были установлены какие-либо файлы cookie, но curl может повторить запрос, который перенаправляет на тот же URL-адрес с опцией -L
.
Вау, это действительно странно.
Как упоминалось в другом ответе, конечная косая черта после имени домена всегда обязательна в HTTP-запросах, поэтому не ожидается, что вы получите перенаправление, если попытаетесь получить доступ к домену "без" какого-либо определенного пути.
Я попробовал ваш домен как curl -v http://jekyllrb.com
, и действительно, только с третьей попытки я действительно получил 200 OK
и содержимое страницы, вместо этого получив 302 Found
по предыдущим двум запросам.
Мой предположим, что выполнение нескольких перенаправлений на себя является простым для клиентов со стандартным поведением, но может быть проблематичным для некоторых сломанных ботов, и GitHub может использовать его как метод, чтобы избежать некоторых сборщиков электронной почты или чего-то подобного? Возможно, аналогично по концепции серому списку в SMTP?
Еще одним потенциальным преимуществом, о котором я мог бы подумать, может быть скорость выполнения отдельных запросов - возможно, у него нет содержимого страницы заранее, поэтому он перенаправляет на вместо этого, гарантируя, что каждый отдельный запрос выполняется очень быстро.
Или, возможно, это делается для минимизации использования пропускной способности, предоставляя перенаправление клиентам, не являющимся браузерами, которые, возможно, не потрудятся сделать второй запрос? Просто еще одна отдаленная догадка.
Cns:cnst {8395} curl -v http://jekyllrb.com; date
* About to connect() to jekyllrb.com port 80 (#0)
* Trying 192.30.252.153...
* connected
* Connected to jekyllrb.com (192.30.252.153) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.26.0
> Host: jekyllrb.com
> Accept: */*
>
< HTTP/1.1 302 Found
< Connection: close
< Pragma: no-cache
< cache-control: no-cache
< Location: /
<
* Closing connection #0
Tue Dec 30 10:57:35 PST 2014
Cns:cnst {8396} curl -v http://jekyllrb.com ; date
* About to connect() to jekyllrb.com port 80 (#0)
* Trying 192.30.252.153...
* connected
* Connected to jekyllrb.com (192.30.252.153) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.26.0
> Host: jekyllrb.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: GitHub.com
< Date: Tue, 30 Dec 2014 18:57:36 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 8177
< Last-Modified: Mon, 22 Dec 2014 14:17:25 GMT
< Expires: Tue, 30 Dec 2014 19:07:36 GMT
< Cache-Control: max-age=600
< Accept-Ranges: bytes
<
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Jekyll • Simple, blog-aware, static sites</title>