Неоплачиваемый information headers. Исправление ошибки: cannot modify header information – headers already sent by

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

Все статьи из цикла:

  • Что такое Http заголовки. Общая теория.

HTTP расшифровывается как HyperText Transfer Protocol (протокол передачи гипертекста). Протокол — это набор правил, по которым разные устройства обмениваются данными. Он был создан в 1990-х годах. Сейчас он используется в сети интернет практически повсеместно. Всё, что вы видите в окне браузера, было получено посредством этого протокола. http заголовки — пожалуй главная вещь в общении между устройствами. Они передают основную информацию об устанавливающемся соединении и о передаваемой информации через это соединение.
Взглянем на схему общения двух устройств. Пусть этими устройствами будут ваш компьютер и какой-нибудь сервер в интернете:

Как видно, браузер отослал http-запрос. Он может выглядеть примерно так:

GET /other-19 HTTP/1.1
Host: www.scriptsite.ru
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; ru; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

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

Server: Apache/2.0.61 (Unix) mod_ssl/2.0.61 OpenSSL/0.9.8k mod_dp20/0.99.2 PHP/5.2.5 mod_python/3.3.1 Python/2.5.1 mod_ruby/1.2.6 Ruby/1.8.6(2007-09-24)

X-Powered-By: PHP/5.2.5

Set-Cookie: PHPSESSID=ft47gokfee6amv3eda3k1p93s3; path=/

Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0

Pragma: no-cache

Keep-Alive: timeout=10, max=1024

Connection: Keep-Alive

Transfer-Encoding: chunked

Content-Type: text/html

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

Как увидеть http-заголовки?

Для того, чтобы увидеть http-заголовки, я рекомендую следующие плагины для браузера firefox:

Если вы пользуетесь браузером Chrome, просмотреть всю информацию можно, нажав на кнопку настройки — инструменты — инструменты разработчика. Вкладка networks.
Пользователям браузера opera ничего посоветовать не могу, так как не дружу с этим браузером. Установив плагины и запустив их, попробуйте обновить страницу. Вы сразу же увидите огромные списки запросов и ответов, посредством которых ваш браузер общался с сервером.

Http-заголовки и доступ к ним в php

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

И мы получаем распечатку массива заголовков.

Но чаще к ним обращаются через глобальную переменную $_SERVER. Почти для каждого http заголовка есть аналогичное название элемента в этой переменной, образуемого по принципу HTTP_имя_заголовка. Так для того же ‘User_Agent’ есть переменная $_SERVER[‘HTTP_USER_AGENT’];

Для получения заголовков, которые сервер собирается отправить пользователю, используется функция headers_list() . Как правило, сервер составляет недостающие обязательные заголовки уже в конце работы всех скриптов. Поэтому этот массив будет содержать заголовки либо те, которые сервер создал перед началом выполнения скрипта (и они не будут изменены), либо те, которые мы установили вручную. Вручную их можно установить с помощью функции header(«текст заголовка»);
Выполним такой код:

Увидим распечатку готовых к отправке на момент вызова функции заголовков:

Первый заголовок был установлен автоматически, и он несёт в себе название сервера, на котором выполняется скрипт. Второй - установленный нами вручную. Если бы браузеру нужен был заголовок «Фрукт», он бы взял его из http-ответа сервра и использовал. Но так как наш браузер не нуждается в нём, то он просто игнорирует непонятную ему строку.

Структура http запроса

Наш запрос выглядит следующим образом:

Первая строка в нём, как уже было сказано раньше, является строкой запроса. Она состоит из трёх частей:

  • method (метод) — указывает, какого рода запрос. Самые распространённые методы: GET, POST, HEAD. О них будет написано в следующем параграфе.
  • path (путь) — как правило, это часть URL, идущая после домена. Например, если вы вводите в адресную строку http://www.scriptsite.ru/about/, значение path будет /about/.
  • protocol (протокол) — используемый протокол. Как правило, состоит из «HTTP» и версии протокола. Обычно, в современных браузерах используется версия 1.1

Дальше идут заголовки в виде строк формата «Имя: значение».
Кстати, данные о cookies также передаются в этом запросе в виде одного из заголовков. Большинство из этих строк не являются обязательными. Запрос может быть сокращён вообще до двух строк:

GET /article/show/4/ HTTP/1.1

Host: scriptsite.ru

Методы запроса

GET

get-запрос обычно используется для запроса документа с передачей некоторых параметров.
Это основной метод, используемый для получения html-страниц, изображений, CSS и JavaScript файлов, и т.д.
Из-за того, что параметры могут быть любыми, а на сервере нет ограничений по способам их обработки, часто метод для запросов данных используют для передачи информации. Например, у нас будет такая форма

При этом эти параметры будут видны в адресной строке браузера.

POST

Post — метод, используемый для отправки данных на сервер. Несмотря на то, что вы можете отправлять данные серверу методом GET через адресную строку браузера, в большинстве случаев предпочтительнее использовать POST. Отправлять большие объёмы данных через GET непрактично. К тому же GET имеет некоторые ограничения, не позволяющие, например, опубликовать эту статью на моём сайте через одну лишь строку браузера. POST запросы чаще всего используются для передачи web-форм. Давайте изменим форму из предыдущего примера, задав ей метод POST

Сегодня мы решили рассказать о том, что значит сообщение «Warning: Cannot modify header information — headers already sent by (output started at /home/...» , появившееся на странице сайта вместо его основного содержимого.
Как оказалось, в сети достаточно написано на эту тему, но нет обобщенной инструкции о том, что все это значит и как от этого избавиться.
Мы решили добавить несколько капель в огромное море информации на эту тему, поскольку столкнулись с данной проблемой лично.

Некоторое время назад мы осуществили перенос нескольких клиентских сайтов с одного хостинга на другой.
Все прошло нормально, сайты были доступны, но при попытке зайти в админ. панель, после ввода логина и пароля вместо панели управления появлялась белая страница.
Проверили на остальных сайтах — тоже самое.
Для того, чтобы узнать возможные причины, мы включили отображение ошибок.
Для этого необходимо по FTP отредактировать файл.htaccess, находящийся в корне сайта, добавив в него строку:

Php_flag display_errors on

После этого при входе в админ.панель появилось несколько сообщений вида «Warning: Cannot modify header information — headers already sent by (output started at /home/.../functions.php:1552) in /home/.../public_html/wp-login.php on line 362» и т.п.

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


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


Если содержимое сайта передается до заголовков, то возникает ситуация, о которой нас предупреждает сообщение «Warning: Cannot modify header information — headers already sent by...»

В каких ситуациях это может возникать? Как уже говорили, в современных CMS заголовки являются результатом работы одной или нескольких функций. Сама функция это некий фрагмент кода, заключенный между начальным и конечным ?> тегами.

Все, что находится за пределами этих тегов считается контентом страницы.
Таким образом, если в начале страницы находятся функции, результатом работы которых являются отправляемые заголовки, и мы получаем сообщение «Warning: Cannot modify header information...», то получается что какая-то информация, относящаяся к контенту страницы отправляется с сервера до заголовков.

Что это за информация и как её найти. Чаще всего это пробелы и пустые строки.

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

Нужно скачать файлы, указанные в сообщениях «Warning: Cannot modify header information...» на локальный компьютер, открыть в редакторе кода (я использую NotePad++) и внимательно проверить на наличие пустых строк и пробелов:

При этом есть одна важная особенность, которая может значительно увеличить время на поиски решения.
В файле может не оказаться пустых строк и пробелов, но если он был сохранен в кодировке UTF-8, то посторонний символ в самом начале документа может вставить редактор, в котором создавался файл. Этот символ — идентификатор UTF-8, равный пробелу с нулевой шириной, который в редакторе может вовсе не отображаться, но на сервере будет воспринят, как основное содержание и выведен до заголовков.

Для того, чтобы избавиться от данного идентификатора, необходимо пересохранить скаченные файлы в формат UTF-8 without BOM (UTF-8 без BOM).

С этой задачей отлично справляется NotePad++.

После этих действий и обновлений файлов на сервере, сообщение должно исчезнуть и сайт будет работать в привычном режиме.

Ошибку эту исправить несложно.
Часто такое же сообщение появляется при старте сессий, в немного другой формулировке:
Warning: Cannot send session cookie - headers already sent
Warning: Cannot send session cache limiter - headers already sent

Byte Order Mark
Иногда вы проверили ВСЁ - нигде ничего нет. Смените редактор. Посмотрите свой файл в другой программе. К примеру, Windows Блокнот при использовании кодировки Unicode добавляет в начало вашего файла служебный символ Byte Order Mark , никак при этом не ставя вас в известность. Откройте скрипт в другом редакторе и удалите посторонние символы. И смените Блокнот на другой редактор.
Или сохраняйте в кодировке UTF-8 without BOM

Многочисленные вопросы на форуме заставляют меня сделать здесь важное замечание:
Эта ошибка появляется не от того, что у вас в скрипте "что то написано выше". А от того, что РНР выводит что-то в браузер. Это не обязательно код. Это может быть сообщение об ошибке . может быть пробел или хтмл тег. Да-да. Для самых талантливых: речь идет о любом символе, отправленном в браузер, а не только о тех, которые браузер отображает неискушенному пользователю. У HTML страниц есть исходный текст. И именно он является результатом работы PHP скрипта, а не красивые буковки с картиночками, как думает очень большое количество людей.

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!

Это сообщение об ошибке часто встречают программисты, начинающие использовать 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 скрипт сохранить в таком формате, то этот байт будет воспринят как часть вывода тела страницы, чего нельзя допускать во избежание рассматриваемой нами проблемы.


 

Возможно, будет полезно почитать: