Как показать узел, но вернуть ответ HTTP 404


Я хочу нормально отображать существующую страницу(узел), но возвращать HTTP404/410 и т. Д. Вместо HTTP200.

Как я могу это сделать? Есть ли какой-нибудь простой способ сделать это?

Author: Mołot, 2014-04-19

2 answers

Встроенные механизмы Drupal

Для доставки 404 страниц для вас бесполезны. Мы можем прочитать:

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

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

Общие функции заголовка Drupal

Может помочь вам. Особенно drupal_add_http_header(). Позвольте мне подчеркнуть одну вещь в его описании:

$значение: значение заголовка HTTP; если равно FALSE, указанное заголовок не установлен. Если $name - "Статус", ожидается, что это будет код статуса, за которым следует фраза причины, , например "404 Не найдено".

Итак, вы хотите установить статус 404:

drupal_add_http_header('Status', '404 Not Found');

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

Кроме того, вам может быть интересно зарегистрировать его, как и другие 404 ошибки:

 watchdog('page not found', check_plain($_GET['q']), NULL, WATCHDOG_WARNING);

Где его разместить?

Это зависит от того, что вам нужно решить, должна ли страница быть 404 или нет. Если все, что вам нужно, это фактические данные на странице, вы можете перейти к hook_page_delivery_callback_alter():

Этот крючок предназначен для изменения обратного вызова доставки на основе информации , не связанной с путем доступа к странице . Например, его можно использовать для установки обратного вызова доставки на основе заголовка HTTP-запроса (как показано в примере кода). Чтобы указать обратный вызов доставки на основе информации о пути, используйте hook_menu() или hook_menu_alter().

Акцент мой.

Предположим, что вам это нужно для узлов

И это означает, что вам нужен идентификатор узла. NID является частью пути, поэтому, следуя приведенному выше предложению, вы хотите использовать hook_menu_alter().

Давайте посмотрим на , как выглядит меню узла . Часть, которую мы хотим изменить, это:

  $items['node/%node'] = array(
    'title callback' => 'node_page_title',
    'title arguments' => array(1),

    // The page callback also invokes drupal_set_title() in case
    // the menu router's title is overridden by a menu link.
    'page callback' => 'node_page_view',
    'page arguments' => array(1),
    'access callback' => 'node_access',
    'access arguments' => array('view', 1),
  );

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

  1. Выполните любую необходимую логику
  2. Установите заголовок так, как вам нужно
  3. Войдите в систему сторожевого пса, если хотите
  4. Вызовите исходный обратный вызов и верните его результат. Каскад рендеринга явно не устанавливает HTTP 200 later, поэтому ваш заголовок состояния должен быть доставлен без изменений. Если, конечно, некоторые модули не изменят его, но это то, чего мы не можем знать.

Последние заметки

Благодаря Айеш К и МПД:

  • Отправляющий заголовок теперь может работать в любом из крючков предварительной обработки или практически в любом tpl.php файл. Тот факт, что вы могли бы, не означает, что вы должны, особенно в файлах tpl, так как это может помешать кэшированию, но стоит помнить, что вы не ограничены способами, которые я описал выше. Например hook_page_alter() тоже может быть безопасным выбором.

  • Убедитесь, что размер страницы превышает 512 байт, в противном случае некоторые браузеры (Привет, IE) будет игнорировать это.

  • Имейте в виду, что по RFC 2616

    Агенты пользователей ДОЛЖНЫ отображать пользователю любую включенную сущность.

    Как вы можете заметить, этот RFC использует MUST в некоторых случаях, и это не один из них, поэтому, если браузер откажется отображать вашу страницу после отправки 404, это не совсем ошибка. Браузерам не запрещено игнорировать ваш HTML-код при отправке 404.

 17
Author: Mołot, 2017-04-13 12:47:11

Использовать drupal_add_http_header()

Поместите это внутри узла с помощью фильтра PHP (что обычно является плохой идеей).

drupal_add_http_header('Status', '404 Not Found');

ИЛИ поместите это внутри вызова hook_init.

// Get the current active node object if present.
$node = menu_get_object();
if (!empty($node) && !empty($node->nid) && $node->nid == 86) {
  drupal_add_http_header('Status', '404 Not Found');
}
 4
Author: mikeytown2, 2014-04-23 16:05:41