Отображение страниц ошибок при отправке заголовка с функцией header () - PullRequest
0 голосов
/ 12 февраля 2012

Я хочу отправить несколько кодов ответа в ответ (что еще?) На различные условия.

Заголовок отправляется - я споткнулся о различных ошибках, которые вы можете сделать с помощью header (), таких как вывод перед вызовом. Я выяснил такие проблемы, например, теперь я использую ob_start () и ob_clean () перед вызовом функции header ().

Теперь мне нужно понять, почему мой браузер / сервер / что-то еще не показывает мне страницу ошибки.

Вот HTML-страница, которую я использую для тестирования:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Header Testing</title>
</head>
<body>
<?php
     error_reporting(E_ALL);
     ini_set('display_errors', '1');
     ob_start();
     ob_clean();
     header("HTTP/1.1 403 - Forbidden", true, 403); // I get the same results with or without "true, 403"
     ob_flush();
?>

Вот заголовок из журнала доступа:

127.0.0.1 - - [11/Feb/2012:19:14:35 -0600] "POST /commentprocessing.php HTTP/1.1" 403 266 "http://127.0.0.1/submitcomments.php" "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.24) Gecko/20111103 Firefox/3.6.24 ( .NET CLR 3.5.30729; .NET4.0C)"

Вот источник HTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Header Testing</title>
</head>
<body>
</body></html>

Это именно то, что я получил бы, если бы удалил код PHP со страницы тестирования.

Есть ли способ автоматически отображать страницу с ошибкой на основе кода возврата в заголовке?

Я использую сервер Abyss для такого рода тестирования. У меня есть пользовательская страница ошибок, определенная в Abyss для ошибок 403, и я проверил, правильно ли она написана в настройке Abyss, и эта страница действительно существует.

Эта страница не отображается для заголовка с кодом ответа 403. Похоже, что он отправлен правильно, поскольку отображается в журнале доступа.

Может ли это быть проблемой с моим использованием Abyss локально, а не с сервером моей хостинговой компании?

Есть предложения?

EDIT ***

tftd

Если то, что вы сказали, верно, что сервер игнорирует мой код, почему он регистрируется в журнале доступа с указанным мною кодом?

И, если вы сказали, что не можете изменить код ответа, почему даже есть оператор header () ИЛИ почему в документации четко не указано, что такие вещи, как использование ob_start () и ob_clean () won '? Решить обойти это.

В более чем одном месте я вижу ссылки на использование ob_start () и ob_clean () для удаления сгенерированного вывода, чтобы сработал вызов header ().

Heera

Спасибо, по крайней мере, за то, что показали мне, что материал может быть помещен над утверждением doctype и при этом оставаться эффективным. Я бы не подумал, что это сработает. Итак, спасибо вам за это.

Однако ваш пример просто выводит именно то, что было бы выведено, если вы удалили весь PHP и имели только HTML.

Я удалил ваш вызов onload, чтобы устранить ошибку «функция не определена», которая возникла бы, поскольку вы не включили скрипт, содержащий функцию, на которую ссылаются.

Следующий вывод будет такой же, как в вашем примере:

<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>

Вот ваш пример, который выдает тот же вывод, что и прямой HTML выше.

<?php ob_start();?>
<!DOCTYPE html>
<html>   <head></head>>
<body>
This is some text
</body>></html>
<?php
$ob=ob_get_clean();
echo $ob;
ob_end_flush(); ?>

Вы совершаете запутанное путешествие к тому же выходу.

Кроме того, зачем достать содержимое буфера, развернуть его и вывести его? Что это демонстрирует, кроме вызова ob_get_clean (), возвращает содержимое буфера, стирает его и, в отличие от ob_clean (), удаляет буфер, и если вы хотите отправить только что удаленный вывод, вы должны использовать ob_get_clean ( ) и сохраните его, а затем используйте echo для его записи.

Разве это не демонстрирует, что вам лучше сделать что-то для сохранения содержимого буфера, если вы хотите вывести его перед вызовом чистой функции?

И, ob_end_flush () задокументирована, везде, где я сталкивался с этим, так как при автоматическом вызове сценарий / страница заканчиваются. Зачем демонстрировать что-то, что происходит автоматически, если только вы не показали, что при отсутствии вызова flush того или иного типа результат будет одинаковым, при условии, что дополнительный вызов out не создается после вызова flush.

Похоже, ваш вызов ob_end_clean () вообще ничего не демонстрирует, хммм или нет?

Итак, зачем генерировать вывод, получать его из буфера, стирать и удалять буфер, а затем выводить содержимое, которое вы сохранили? Что именно это демонстрирует? Как сделать что-то простое запутанным, странным образом?

Теперь, если вы хотите продемонстрировать разницу между размещением ob_start () на выходе и тем, что ob_clean () удаляет предыдущий вывод, почему бы не начать с примера, подобного этому:

<?php ob_start();?> 
<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>
<?php
ob_clean(); // erase output buffer
echo "It was the best of times, it was the worst of times."
?>

Единственный выход из этого будет

It was the best of times, it was the worst of times.

Если вы закомментируете вызов ob_clean ():

<?php ob_start();?>
<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>
<?php
//ob_clean(); // erase output buffer
echo "It was the best of times, it was the worst of times."
?>

Вывод теперь:

<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>
This is some textIt was the best of times, it was the worst of times.

Если вы возьмете мой оригинальный пример и переместите ob_start () во второй кусок PHP-кода, например:

<!DOCTYPE html>
<html>
<head></head>
<body>
This is some text
</body>
</html>
<?php
ob_start();
ob_clean(); // erase output buffer
echo "It was the best of times, it was the worst of times."
?>

Вывод:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
This is some text
</body>
</html>
This is some text It was the best of times, it was the worst of times.

Это примеры, которые я привел бы для демонстрации эффекта размещения вызовов ob_start () и ob_clean ().

Опять же, ваш пример делает именно то, что сделал бы HTML, если бы не PHP.

Если бы вы говорили, что вы должны использовать ob_start, ob_get_clean (), echo и ob_end_flush () для получения выходных данных - я бы ожидал этого от программиста, который знал только о ob_get_clean () и ob_end_flush ().

Я ожидаю, что от программиста, который по какой-то причине думал, что он или она должны взять на себя ответственность, чтобы получить вывод для пользователя; что они должны были взять содержимое буфера и использовать echo для отправки его пользователю.

Я просто не понимаю, почему вы написали этот пример, как вы, или что, помимо размещения ob_start (), вы пытались продемонстрировать.

Что касается «реального мира» - в реальном мире программисты должны понимать языковые функции, которые они используют, и любые альтернативы им. Предполагается, что они понимают такие концепции, как, например, PHP, автоматически отправляющий любой сгенерированный вывод без необходимости вызывать функцию, чтобы получить ее пользователю.

Вы назвали мое использование буферизации неправильным. Что ж, так и было, что касается размещения вызова ob_sat (), но все остальное просто отлично.

Если бы вы опубликовали свой пример в каком-то вопросе, мой ответ был бы -

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

Извините, но этот пример, за исключением размещения ob_start, не демонстрирует ничего, кроме странного и условного способа передачи HTML пользователю.

Возможно, вы просто не нашли время, чтобы рассмотреть лучший пример для использования, после того, как сначала решили, что пример должен был продемонстрировать.

Если мы игнорируем тот факт, что пример не делает ничего, что делает прямой HTML, и он идет о выводе буфера в запутанном виде, все, что сделал ваш пример, указало мне одну вещь - вы можете поместить что-то перед doctype и это будет "обработано. И я благодарю вас за то, что указали мне на это.

mc_kennedy

Я прочитал страницу, на которую вы указали, но я не думаю, что это применимо, поскольку первая строка вывода не начинается с HTTP /, как указывает страница.

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

Всем в целом -

Похоже, что некоторые люди говорят, что вы должны иметь вызов header () в самом верху файла, и это позволит вам правильно отправлять коды ответов.

Ну, я попробовал это, с PHP на самом верху, а затем со стандартным HTML, и я не вижу никакой разницы.

Я ошибаюсь, думая, что сервер будет по-разному реагировать, скажем, на 200, а не на 403?

У меня все это неправильно, и то, что я ожидаю - заставить сервер как-то реагировать на ошибку 403 или 500 - это просто нечто, чего не существует?

Если использованный мною подход приводил к игнорированию вызова header (), почему в журнале отображается код, который я отправлял?

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

Но ожидаю ли я, что сервер будет по-разному реагировать на разные коды ответов, а этого просто не происходит?

Bob

Ответы [ 4 ]

0 голосов
/ 12 февраля 2012

Помимо других ответов, вы неправильно используете буферизацию объектов, вот простой пример этого

<?php ob_start();?>
  <!DOCTYPE html>
  <html>
  <head></head>
  <body onload="initialize()">
     This is some text
  </body>
 </html>
<?php 
  $ob=ob_get_clean(); 
  echo $ob; 
  ob_end_flush();
?>

В реальном мире вы должны использовать его по-другому, это всего лишь пример.

0 голосов
/ 12 февраля 2012

Функция header() изменяет только существующие заголовки, отправленные вашим веб-сервером.

В вашем случае вы не можете изменить статус. Открыв http://localhost/index.php, вы отправляете запрос в Abyss, который ищет index.php. Если он находит файл - он открывает / выполняет его. И поскольку ваш файл действительно существует, Abyss / Apache / Nginx будет действовать, если вы отправляете Status: 200.

Даже если вы отправите header('Status: 403');, сервер не выполнит его. Я не уверен, есть ли возможность переопределить ответ сервера так, как вы этого хотите, но с apache, nginx вы не можете этого сделать.

Edit: Как сказал @Alex Lunix - вы можете перенаправить пользователя на страницу ошибки через
header("Location: path/to/your/error/page");

0 голосов
/ 12 февраля 2012

Возможно, вы захотите проверить, как ваш сервер Abyss обрабатывает ваш PHP-скрипт.Поскольку запись в журнале указывает, что вы отправляете ответ 403, сервер, вероятно, рассматривает сценарий как сценарий NPH и, таким образом, отправляет вывод, включая заголовки, непосредственно в браузер без каких-либо других действий (таких как проверка, должен ли он перейти кнастроенная страница 403).Подробнее см. http://www.aprelium.com/data/doc/2/abyssws-win-doc-html/cgiinternals.html.

0 голосов
/ 12 февраля 2012

Отправка кода ответа в PHP не должна также пересылать их на страницу ошибки. Использовать заголовок («Location: / error / page / url»); переслать их на страницу, и если на страницах с ошибками уже отправлен код ответа, отправлять его перед отправкой не нужно.

И проблема с уже отправленными заголовками связана с тем, что уже отправлено содержимое, заголовки нужно отправлять раньше всего другого содержимого. Так что размещение над html исправит это.

<?php
     if(Condition for 403){
         header("HTTP/1.1 403 - Forbidden", true, 403);//Tell the user that this page is forbidden (not necessary if /error/file/ sends response)
         header("Location: /error/file/"); //Forward user to your error page
         exit; //Used to prevent php from executing further in the script
     }
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Header Testing</title>
</head>
<body>

EDIT:

Причина, по которой вы размещаете ее сверху, заключается в том, что они отправляют перед любым выводом (что и делает буферизация вывода, но добавляет ненужный код). Отправка кода ответа сообщает пользователю о характере страницы: если вы пишете страницу с ошибкой 404, вы отправляете ответ 404. Если на этой странице вы хотите 403, вам нужно перенаправить их на свою страницу 403, используя заголовок Location.

...