Статьи

Нет-Обновить ссылки

Это стало относительно обычным делом, чтобы видеть ссылки на веб-сайтах, которые фактически не заставляют браузер загружать новую веб-страницу. Многие такие ссылки используются для запуска клиентских сценариев JavaScript, которые каким-то образом изменяют существующую страницу. Другие примеры этого эффекта включают различные калькуляторы валют, которые доступны онлайн, где вы вводите сумму в одной валюте в одно поле формы, затем нажимаете кнопку, а затем эквивалентная сумма в другой валюте появляется во втором поле формы — все без загрузки новой страницы.

Общим потоком, связывающим эти примеры, является использование элемента HTML, который был разработан для извлечения новых веб-страниц, но был использован таким образом, чтобы это не происходило. При нажатии на ссылки обычно загружается новая веб-страница. Формы при отправке обычно отправляют их содержимое на веб-сервер вместе с запросом на новую веб-страницу. Используя клиентские сценарии, можно легко предотвратить это, чтобы достичь какого-то другого эффекта.

Но что, если скриптов на стороне клиента недостаточно? Что если действие, которое необходимо выполнить при нажатии на ссылку или отправке формы, должно выполняться серверным сценарием (например, обновление базы данных)? Можно ли это сделать без загрузки новой страницы в окне браузера?

Это был вопрос, заданный мне Клодом Нидхэмом в раннем выпуске Tech Times . И он, и я видели этот эффект в действии. Он видел, как www.mp3.com легко добавлял песню в свой личный список треков, когда нажимал на ссылку на их сайте. Я видел, как www.milehighcomics.com добавлял товар в корзину, когда заполнял и отправлял небольшую форму. Обе эти задачи были выполнены без каких-либо изменений в отображении страницы (как сказал Клод, «даже не мерцание».)

Сначала я нашел этот эффект довольно отвлекающим. В конце концов, когда пользователь сайта онлайн-покупок делает что-то столь же важное, как добавление товара в свою корзину, он вправе ожидать какой-либо обратной связи в ответ на это действие. Тогда я понял, что ссылка «без обновления» не должна исключать соответствующую обратную связь. Например, можно одновременно отобразить простое всплывающее сообщение JavaScript «Этот элемент был добавлен в вашу корзину».

Тогда встал вопрос, как создать ссылку, которая отправляет запрос на веб-сервер без изменения текущего просмотра страницы. К сожалению, мои запросы фирм веб-дизайна, которые достигли этого эффекта, остались без ответа. Казалось, что метод создания ссылок без обновления был чем-то вроде секрета. Некоторые идеи, выдвинутые читателями Tech Times, включали загрузку полученной страницы в невидимый фрейм и долгое время вызывать сценарий на стороне сервера, вызываемый запросом. Первое является относительно хорошим решением, за исключением того, что Netscape не работает совместно, когда дело доходит до создания кадров с нулевой шириной или высотой. Последнее решение, хотя и творческое и более близкое к тому, что я имел в виду, привело бы к большому количеству зомби-процессов, оставшихся на сервере.

Так как это сделано?

Затем Фабио Диас написал мне на Рождество (насколько это уместно!) С многообещающим лакомым кусочком, который он нашел скрывающимся в спецификации протокола передачи гипертекста (HTTP). Для тех, кто не знает, HTTP — это протокол, используемый для связи между веб-браузерами и веб-серверами. По сути, HTTP-связь инициируется браузером, который запрашивает страницу. Затем веб-сервер отвечает на этот запрос, сначала с помощью кода, который указывает тип ответа, а затем с HTML-содержимым для новой страницы, если это необходимо. Наиболее распространенный код ответа — 200, что означает успешный запрос с запрошенной веб-страницей. Другой знакомый код ответа — 404, означающий, что запрошенный документ не существует.

Фабио заметил код ответа 204 — ответ «Нет контента». Этот ответ говорит браузеру: «Я сделал то, что вы просили, но у меня нет новой страницы для отображения». Оказывается, именно так работают ссылки без обновления на www.mp3.com и www.milehighcomics.com!

Хотя любой серверный язык сценариев может использоваться для генерирования 204 No Content response Следующее будет нашей ссылкой, которая буквально ничего не делает:

 <a href="204.php">Click me!</a>

Аналогичным образом, следующая форма будет представлять собой форму, которая не вызывает видимых изменений на странице:

 <form action="204.php" method="POST">

Это обычная HTML-ссылка и обычная HTML-форма; магия в 204.php

 <? header("HTTP/1.0 204 No Content"); ?>

Эта единственная строка PHP возвращает ответ 204 No Content Если ваш веб-сервер оснащен PHP, попробуйте сами! Если ваш сервер выдает ошибку 500 (внутренняя ошибка сервера), велика вероятность, что вы используете сервер Apache с версией PHP для CGI, а не (более быстрый и мощный) модуль Apache. В таких конфигурациях вы должны вместо этого использовать следующий альтернативный синтаксис:

 <? header("Status: 204 No Content"); ?>

Какой бы код вы ни использовали, при нажатии на ссылку ваш браузер не должен делать абсолютно ничего. Однако в зависимости от конкретного браузера и веб-сервера, который вы используете, может появиться небольшая анимация, которая указывает, что ваш браузер загружает страницу. Это неприятный побочный эффект этого метода, который делает включение соответствующей обратной связи тем более важным. Например, следующие варианты ссылки и формы уведомят пользователя о предпринятом действии:

 <a href="204.php" onClick="alert('Done!');">Click me!</a>
 <form action="204.php" method="POST" onSubmit="alert('Done!');">

В этом случае обратная связь не так уж важна; однако, если бы мы расширили 204.php

 <?  
 $ok = mysql_query("UPDATE Counters SET Hits = Hits + 1 WHERE ID=42")  
         or die("A database error has occurred. Please try again.");  
 
 header("HTTP/1.0 204 No Content");  
?>

Обратите внимание, что приведенный выше скрипт может генерировать или не генерировать страницу в ответ на действия пользователя. Если запрос выполняется нормально, то ответ 204 No Content Если по какой-либо причине запрос не выполняется, вызов die()header()die()

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

Для поклонников ASP в аудитории следующий скрипт (написанный на VBScript) является эквивалентом приведенного выше примера PHP. Он ничего не вернет браузеру, и вы можете заставить скрипт делать все, что пожелаете, добавив в него необходимые команды.

 <% Response.Status = "204 No Content" %>

А вот как это сделать в Perl с использованием CGI.pm:

 print header(-status=>'204 No Response');

Я должен упомянуть одну заметку осторожности. Во всех вышеперечисленных версиях этого небольшого трюка, а также, вероятно, в других языках сценариев, команде, отправляющей ответ 204 No Content Например, в PHP, если ваш скрипт структурирован следующим образом, он завершится с ошибкой:

 <HTML>  
<HEAD><TITLE></TITLE></HEAD>  
<BODY>  
<?  
 if (some condition) {  
   header("HTTP/1.0 204 No Content");  
   exit();  
 }  
?>  
...

Проблема здесь заключается в тегах HTML, которые появляются перед кодом PHP. Ваш сценарий не может решить не отправлять браузеру веб-страницу, когда он уже начал передавать эту страницу в браузер.

Помимо этого, этот метод довольно прост. Это просто показывает, как мы можем принять технологию как должное. Многие из читателей Tech Times и я построили свою карьеру, работая с Интернетом, и тем не менее сам протокол, на котором основана сеть, в значительной степени игнорируется — или, возможно, HTTP просто не так привлекателен, как CSS и JavaScript.

Если вам интересно больше узнать о стандарте HTTP, лучше всего перейти прямо к источнику: RFC 2616: стандарт HTTP 1.1 .