Решение проблемы "Cannot add header information - headers already sent". Что такое Http заголовки (Http headers). Общая теория Безобразный information headers

Это сообщение об ошибке часто встречают программисты, начинающие использовать PHP. Понимание того, почему возникает эта ошибка, поможет найти решение.

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

Эта распространенная ошибка PHP наблюдается когда программист делает ошибки в манипуляции или создания заголовков. Вот пример:

Warning: Cannot modify header information – headers already sent by (output started at /home/usr1/public_html/sent.php:42) in /home/usr1/public_html/includes/theme-header.php on line 12

Как правило, вам не нужно беспокоиться о заголовке, так как он генерируется автоматически и содержит информацию о странице, сервере, и coockie. Информация в заголовке важна, но она обычно не видна пользователю. Вот несколько примеров:

Date: Mon, 10 Jul 2006 18:51:59 GMT Server: Apache/2.2.0 (Unix) mod_ssl/2.2.0 OpenSSL/0.9.7g Content-Encoding: gzip Content-Type: text/html

Иногда программисты хотят изменить некоторые значения заголовка. Например, если PHP генерирует XML вывод, Content-Type должен быть изменен, чтобы указать это. Другим распространенным примером является перенаправление браузера пользователя на другую веб-страницу с помощью элемента заголовка Location, как описано в этой статье .

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

  1. Найдите инструкцию header(), которая является причиной проблемы. Ошибка должна быть на или до этой линии.
  2. Посмотрите на любые инструкции, которые могли бы направить вывод пользователю до этой инструкции заголовка. Если вы обнаружили один или несколько, измените код, чтобы переместить инструкцию заголовка перед ними. Сложные условные операторы могут усложнить проблему, но они также могут помочь решить проблему. Как вариант можете применить условное выражение в верхней части сценария PHP, которое определяет значение заголовка как можно раньше, и устанавливает его там.
  3. Убедитесь, что нет пробелов за пределами начального и конечного PHP тэгов. В то время как пустая строка перед начальным тегом
  4. Если вы сохраняете ваш файл в кодировке UTF-8, то убедитесь, что файл сохраняется без сигнатуры (without BOM). Сигнатура — это байт, добавляемый в начале файла, и если PHP скрипт сохранить в таком формате, то этот байт будет воспринят как часть вывода тела страницы, чего нельзя допускать во избежание рассматриваемой нами проблемы.

С этой ошибкой ко мне постоянно обращаются и спрашивают: "Где ошибка? ". Подобных писем за всё время я получил где-то штук 500 , не меньше. Пора с ошибкой "" уже заканчивать. В этой статье я расскажу о причинах возникновения данной ошибки, а также о том, как её решить.

Если перевести данную ошибку на русский язык, то получится примерно следующее: "Нельзя изменить заголовок, поскольку они уже отправлены ". Что это за "заголовки "? Давайте разберёмся.

Когда сервер возвращает ответ клиенту, помимо тела (например, HTML-кода страницы), идут ещё и заголовки. В них содержится код ответа сервера, cookie , кодировка и множество других служебных параметров. Может ли PHP-скрипт отправить заголовок? Конечно, может. Для этого существует функция header() .

Данная функция, например, постоянно используется при . Также данная функция регулярно используется при .

Также заголовки модифицируются при отправке cookie и при начале сессии (функция session_start() ).

А теперь о том, почему же всё-таки возникает ошибка? Сервер всегда сначала отдаёт серверу заголовки, а потом тело. Если сервер уже вернул заголовки, потом пошло тело, и тут он встречает какой-нибудь session_start() . Оказывается горе-программист забыл отправить заголовки до начала тела, и теперь хочет догнать уже ушедший поезд.

Вот код с ошибкой "":



?>

Разумеется, такой бред PHP не прощает. И надо было писать так:

session_start(); // А давайте начнём сессию
?>

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

Другой пример кода с ошибкой:

echo "Hello!"; // Что-нибудь выведем
session_start(); // А давайте начнём сессию
?>

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

Как будет правильно переписать данный код, подумайте сами.

Ещё пример:




exit;
?>

Когда у автора такого кода, ничего не получается, он удивляется от этой ошибки и говорит: "Очень странное совпадение, когда операция проходит успешно, всё хорошо, а когда какая-то ошибка, мне сообщают Cannot modify header information - headers already sent". Не дословно, но смысл именно в этом.

Проблема та же самая, и правильно писать так:

$error = true; // Были ли ошибки?
if ($error) echo "Произошла ошибка";
else header("Location: ".$_SERVER["HTTP_REFERER"]); // Делаем редирект обратно
exit;
?>

Есть и труднозаметные ошибки:

header("Location: ".$_SERVER["HTTP_REFERER"]); // Делаем редирект обратно
exit;
?>

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

Бывают и следующие ошибки, имеющие всё ту же природу. Допустим есть файл a.html :

require_once "a.html";
header("Location: ".$_SERVER["HTTP_REFERER"]); // Делаем редирект обратно
exit;
?>

И человек искренне удивляется, откуда ошибка, если он ничего не выводил? Поэтому смотреть надо не конкретно 1 файл, а все файлы, которые подключаются в нём. И в тех, что подключаются у подключаемых, тоже надо смотреть, чтобы не было вывода.

И последний момент, но уже более сложный. Оказывается, что иногда эта ошибка происходит и при правильном коде. Тогда всё дело в кодировке . Убедитесь, что кодировка файла "UTF-8 без BOM ", причём именно "без BOM ", а не просто "UTF-8 ". Поскольку BOM - это байты, идущие в самом начале файла, и они являются выводом.

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

Understanding HTTP headers and HTTP header fields

HTTP headers provide vital information required for a HTTP transaction send via http protocol .

The general HTTP header format contains colon-separated name - value pairs in the header field. Each of the name-value pair end with a carriage return (CR) and a line feed (LF) character sequence. Empty fields at the end of each header indicate the end of the header.

The common header format followed by applications looks like:

Types of HTTP headers

There are four types of HTTP message headers. They are:

  • General Header
  • Request Header
  • Response Header
  • Entity Header

General Header

General Header fields have common applicability in request and response messages. The header fields apply only to the transmitted message and do not apply on the transferred entity.

The structure of a general header looks like:

Cache-control field specifies directives that have to be followed by every caching mechanism on a request and response system.

Connection field allows the sender to specify options required for a connection. The connection header has the following format:

Date field represents the date and time during the initiation of the message. The date format specified in HTTP look like:

Pragma field helps to include implementation specific directive applicable to any recipient on a request and response system.

Trailer field value specifies whether a set of header fields in message trailer is encoded with chunk transfer-coding.

Transfer-Encoding field indicate whether any type of transformation is applied to the message body.

Upgrade field enables clients to specify additional supported communication protocols. It also enables the server to switch protocols with the additional protocols.

Via field are mandatory fields used by proxies and gateways which indicate intermediate protocols. It also indicates request recipient between user-agent and server and response between server and client.

Warning field carries additional information on message status and message transformations which are not reflected in the message.

Warning headers are usually sent with responses.

The request header field allows clients to additionally pass request information and client information to the server.

The structure of a request header looks like:

Accept field specifies media types which are acceptable for response.

"*" is used to group media types in range

"*/*" indicate all media types

"type/*" indicate all subtypes of a type

Accept-Charset field indicates response acceptable character sets. It makes clients capable to understand special-purpose character sets to signal the server to represent the document in these character sets.

Accept-Encoding field is similar to Accept, restricts response acceptable content-coding.

Accept-Language field is similar to Accept, restricts preferred set of natural languages.

Authorization field is for user agents who wish to authenticate themselves with the server.

Expect field indicates server behaviors required by a client.

From field contains e-mail address of a user who controls the requesting user-agent.

Host field specifies the internet host and requested resource port number from user URI.

If-Match field is used to make conditional methods.

If-Modified-Since field is used to make a conditional method. If the requested variant is not modified within the specified time, the entity will not be returned from the server.

If-None-Match field allows efficient update of cache information with minimum transaction overhead.

If-Range field allows clients to receive part of the missing entity or otherwise, clients can ask to send the entire new entity.

If-Unmodified-Since field allows the server to perform requested operation if it has not been modified since the time specified in this field.

Max Forwards field provides mechanisms with TRACE and OPTIONS methods to limit the request forwarding proxies or gateways.

Proxy Authorization field allows client to identify to secure proxy.

Range field specifies the HTTP entities in HTTP messages represented as a sequence of bytes. HTTP retrieval request requests one or more sub range of entity using GET methods.

Referrer field allows clients to specify the address URI of the resource from which Request-URI is found.

TE field indicates extension transfer-coding it can accept in the response. Additionally, it indicates whether it will accept trailer fields in chunk transfer-coding.

User-Agent field contains information about the requesting user-agent.

HTTP Response Header

The response header field allows the server to pass additional information through the responses other than simple Status-Line response.

The structure of the response header looks like:

Accept-Ranges field enables servers to indicate acceptance of resource range requests.

Age field indicates sender the approximate amount of time since server responded.

ETag field provides current value of the entity tag for a request.

Location field redirects recipients to locations other than Request-URI to complete identification of a new resource.

Proxy-Authenticate field is a mandatory inclusion for proxy authentication response.

Retry-After field is used as a response when a service is unavailable to indicate the length of period for which service will remain unavailable to the client.

Server field contains information about software used by server to handle requests.

Vary field indicates request field that determine whether a cache is eligible to use the response of a request without revalidation of the response.

WWW-Authenticate field are used when a response message is unauthorized.

Entity header fields define metainformation about the entity-body or the requested resource. The entity-header format looks like:

Allow field list the set of methods supported by Request-URI identified resources.

Content-Encoding field is used as a media-type modifier.

Content-Language field describes natural language for clients of an entity.

Content-Length field indicates the size of an entity represented in decimal number.

Content-Location field provides resource location for an entity when it is accessible from a location other than Requested-URI.

Content-MD5 field provides message integrity check (MIC) using an MD5 digest on the entity body.

Content-Range field specifies where partial body of the full entity-body should be applied.

Content-Type field indicates whether the media type of the entity body is sent to the recipient or GET method is used to send requests.

Expires field provides the date/time after which the response becomes stale.

Last Modified field indicates the date and time of last modification of the variant.

The order in which field name appears in the header when received is insignificant. Conventionally general headers are placed first, followed by request or response header with entity header at the end.

Copyright Notice: Please don"t copy or translate this article without prior written permission from the сайт

HTTP Debugger is a proxy-less HTTP analyzer for developers that provides the ability to capture and analyze HTTP headers, cookies, POST params, HTTP content and CORS headers from any browser or desktop application. Awesome UI and very easy to use. Not a proxy, no network issues!

Submitted by on Thu, 05/04/2017 - 12:55

Описание частной проблемы

После нажатия на кнопку выводится ошибка:

Warning: Cannot modify header information - headers already sent by (output started at C:\OpenServer\domains\testsite\WEB\5_phpRedirect.php:10) in C:\OpenServer\domains\testsite\WEB\5_phpRedirect.php on line 12

Код аналогичен приведённому в данной теме:

Экспериментальный Web

Выберите скрипт для загрузки

Скрипт-обработчик:

Когда это бывает

Ошибка (предупреждение) типа:

Warning: Cannot modify header information - headers already sent by

Возникает, если вы уже сделали что-то что требует установки заголовков браузера, а теперь хотите переписать их новыми. Например, если вы уже вывели текст - то php выставляет заголовки (в частности заголовок Location -- которые показывает оставаться ли на запрошенной странице или же нужно нужно перейти на другую страницу и уже там получить ответ на запрос), чтобы показаться браузеру клиента (в своём ответе) как себя вести.

Корень проблемы

Скорее всего, проблема в вашем случае состоит в том, что вы уже отдаёте контент (html-тэги которые перемешаны в файле со скриптом) до команды :

Echo header($redirect);

Помните, что функцию header() можно вызывать только если клиенту еще не передавались данные . То есть она должна идти первой в выводе, перед ее вызовом не должно быть никаких HTML тэгов, пустых строк и т.п. Довольно часто возникает ошибка, когда при чтении кода файловыми функциями, вроде include или require, в этом коде попадаются пробелы или пустые строки, которые выводятся до вызова header(). Те же проблемы могут возникать и при использовании одиночного PHP/HTML файла.

То есть необходимо избавить скрипт-обработчик от html -- ведь он по сути сам ничего не выводит а просто перебрасывает на другой адрес -- это первое .

Header($redirect);

Echo header($redirect);

Эксперимент

Так как echo() вообще-то пишет в тело http ответа , а не в заголовки, а header возвращается void (то есть не возвращает значений), о чём было сказано выше , то смысла в использовании echo() нет, но
-- тем не менее, предлагаю провести эксперимент:

  1. уберите html
  2. не убирайте echo

Так как header() вызывается у вас по сути до echo() (так как header() является аргументом echo()) а значит возврат -- заодно проверим если функция возвращает null -- будет ли это интерпретироваться как пустая строка или же (что вернее) echo даже не начнёт работать как уже произойдёт редирект.

Ещё раз уточним причину

Т.е. перед вызовом header() не должен выводиться никакой контент (о чем написано к описанию функции: http://php.net/manual/ru/function.header...)

  • 1) ни с помощью echo
  • 2) ни с помощью обычного вываливания в браузер html-текста.

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

вопрос решился

По Вашему совету были удалены теги HTML. Теперь переадресация происходит корректно, скрипт-обработчик выглядит так:

Функция echo действительно не влияет на работу, т.е. можно оставить и как у С. Хольцнера:

Также при оформлении кода для редиректа следует обратить внимание на расширение файла, на который производится переход: при предложенном синтаксисе, оно должно быть указано в аргументе header.

  • Log in to post comments

Но можно заставить работать и

Но можно заставить работать и предыдущий обработчик

Перенаправление пользователя

если выставить в файле php.ini опцию

Output_buffering = 4096

  • Log in to post comments

Повторная отправка заголовков запрещена , HTTP - протокол так не работает! Но что ж делать то? Если после вывода на странице, нужно ещё и сессию стартануть и кУку поставить? - Вспоминаем про буферизацию вывода.

То есть когда выставлен ненулевой размер буфера, то пока он не заполнится ещё есть возможность манипулировать заголовками. При нулевом же размере буфера, после вывода контента, его отдача сразу же предваряется передачей клиенту заголовков http-ответа.

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

Но: решать проблему таким способом конечно нельзя (не сильно корректно, точнее).

_____________
матфак вгу и остальная классика =)

  • Log in to post comments