Проверка корректности запроса
Все основные функции движка уже готовы. Во всяком случае, те, что отвечают за выборку контента и навигацию. Осталась одна деликатная тема: что делать, если кто-то запросил некорректный URL?
Статические сайты обслуживаются сервером – если запрошенный файл не найден, сервер выдаст заголовок (HTTP Response Header) с кодом статуса «404 Not Found». Но в случае динамического движка отдаваемый документ определяется не по имени файла в URL, а по переданным скрипту параметрам. При неверных параметрах файл скрипта все равно лежит на своем месте, значит сервер запустит его и отдаст код статуса «200 OK». А документа, соответствующего параметрам, нет. Поэтому скрипт должен определить некорректные парамеры и переписать код статуса до начала выдачи документа. И прекратить работу, не пытаясь искать несуществующие данные.
Для такого аварийного завершения нам потребуются всего две вещи. Первая – HTML-файл страницы с сообщением об ошибке – для выдачи в браузер пользователя. Приготовим его заранее и положим в корневую директорию сайта под именем 404.htm (так он у нас прописан в файле конфигурации).
Вторая – функция, которая отсылает HTTP-заголовок с кодом ошибки и прекращает работу скрипта. Выглядит она так:
<?php function err404($pageout=FALSE) { global $charset,$page404; header("Cache-Control: no-cache, no-store"); header("Content-Type: text/html; charset=".$charset); header($_SERVER['SERVER_PROTOCOL']." 404 Not Found"); if ($pageout) readfile('./'.$page404); exit(); } ?>
Глобальные переменные $charset и $page404 определены в файле конфигурации. А параметр $pageout – логическая переменная, определяющая, выдавать страницу с сообщением об ошибке или нет. По умолчанию его значение FALSE – то есть функция только отдаст HTTP-заголовок с кодом статуса и прекратит работу. Версия протокола HTTP берется из переменной окружения SERVER_PROTOCOL, чтобы послать отклик именно с той версией, по которой работает сервер. Если функцию запустить с параметром TRUE, то после передачи заголовка она считает и отправит в поток вывода файл со страницей сообщения. Выдача только заголовка без сообщения может пригодиться в дальнейшем – в тех случаях, когда точно известно, что запрос послан не браузером, а роботом.
В директории /libs создаем файл functn.inc.php – в него помещаем функцию err404() и функцию hierarchy(), описанную в разделе Разбор структуры сайта. В тот же файл записываем функции выборки разделов для меню: getmain(), getsub() и getlevel(), описанные в разделе Выборка разделов для меню. Базовая библиотека готова. Теперь самое время провести проверку корректности запроса. Этот код уже пойдет в начало центрального скрипта main.php
<?php require('libs/start.inc.php'); require('libs/functn.inc.php'); $fakelink=FALSE; // 1. Проверка отсутствия параметров в статическом URL if (!empty($_urlmode) && $_urlmode!='none' && strpos($_SERVER['REQUEST_URI'],'?') !== FALSE) { $fakelink=TRUE; } // 2. Разбор и проверка GET-параметров if (!empty($_GET)) { foreach ($_GET as $key=>$val) { if (in_array($key,$get_arr)) $$key=trim($val); else { $fakelink=TRUE; break; } } } elseif (!empty($_SERVER['QUERY_STRING'])) { $fakelink=TRUE; } else $id='/'; // Если URL некорректен, посылаем 404 Not Found if ($fakelink) err404(TRUE); // Считываем в массив файл структуры $h_arr=file($datapath.'struct.dat'); // Разбираем структуру сайта $hier=hierarchy($h_arr); // Уничтожаем массив с неразобранным файлом структуры – он больше не нужен unset($h_arr); // 3. Проверка наличия запрошенного раздела. Если такого нет, посылаем 404 if (!array_key_exists($id,$hier)) { err404(TRUE); } ?>
В первых двух строках подгружается файл конфигурации и файл с функциями. Затем определяем логическую переменную $fakelink – она работает «флажком», который будет поднят при любом некорректном состоянии URL. Далее начинаем серию проверок.
Первое условие проводит проверку в случае, когда включен режим трансляции статических URL (переменная $urlmode не пустая и не равна 'none'). Из переменной окружения REQUEST_URI берется первоначально запрошенный (не транслированный) URL и проверяется на отсутствие вопросительного знака. Если ссылки статические, его там быть не должно – статические URL параметров не имеют.
Второе условие:
- при наличии GET-параметров (в случае статических ссылок они появляются после трансляции URL) перебирается в цикле массив $_GET. В ходе перебора наименование каждого параметра проверяется на наличие такого имени в массиве разрешенных (массив определен в файле конфигурации). Неизвестное имя параметра вызывает взвод флажка $fakelink в состояние TRUE и выход из цикла. Попутно создаются переменные с теми же именами и теми же значениями, что и у параметров. Возможные пробельные символы в значениях отсекаются.
- при отсутствии GET-параметров считаем, что было обращение к корню сайта. Проверяется переменная окружения QUERY_STRING – она в этом случае должна быть пустой. Но туда могут попасть кое-какие нелепые довески к запросу корня, не попадающие в $_GET – наподобие
http://domain.ru/?=
После первых двух проверок нужно остановить работу скрипта, если запрошенный URL некорректен. Что мы и делаем – при поднятом флажке $fakelink запускается передача статуса «404 Not Found» с завершением работы скрипта.
Далее, если URL корректного формата, считывается структура сайта и формируется массив разделов. И тут же следует третья проверка – если в массиве разделов не обнаружен алиас запрошенного раздела, значит пришел запрос с корректным форматом, но запрошенная страница не существует. В этом случае также выдается статус 404 и скрипт завершает работу.
Если все проверки пройдены благополучно и запрошенный раздел существует, можно наконец выбирать контент, формировать меню и собирать страницу.