Получение метода HTTP запроса: возможности PHP

Раздел: Веб-программирование PHP -> HTTP методы

Основные способы определения HTTP метода в PHP

Наиболее эффективное решение для получения HTTP-метода запроса в PHP - использование суперглобального массива $_SERVER с ключом 'REQUEST_METHOD'. Этот способ работает во всех актуальных версиях PHP и поддерживается любым веб-сервером.

<?php
$method = $_SERVER['REQUEST_METHOD'];
echo $method; // GET, POST, PUT и т.д.
?>

Php http method (определение http метода в php)

Код обращается к элементу массива, который всегда содержит строку с именем метода (в верхнем регистре). Если запрос пришёл, например, через командную строку (CLI), то $_SERVER['REQUEST_METHOD'] может отсутствовать - потребуется дополнительная проверка.

Типичная ошибка:

Попытка использовать $_SERVER['REQUEST_METHOD'] без предварительной проверки существования ключа может вызвать предупреждение Undefined array key в PHP 8.x или ошибку уровня Notice в более старых версиях. Решение - обернуть обращение в isset() или использовать оператор объединения с NULL (??).

<?php
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET'; // значение по умолчанию
echo $method;
?>

Также стоит учитывать, что при использовании встроенного сервера PHP (php -S) поведение идентично, но некоторые переменные окружения могут отсутствовать.

Как получить метод запроса с помощью filter_input?

Функция filter_input позволяет безопасно извлечь значение внешней переменной и одновременно применить фильтрацию. Для HTTP-метода можно использовать INPUT_SERVER с типом фильтра FILTER_SANITIZE_STRING (или FILTER_UNSAFE_RAW).

<?php
$method = filter_input(INPUT_SERVER, 'REQUEST_METHOD', FILTER_SANITIZE_STRING);
echo $method;
?>

Этот вариант предпочтителен, если нужно гарантировать отсутствие вредоносных символов в значении метода. Однако filter_input возвращает null или false при отсутствии переменной, поэтому результат также следует проверять.

Возможная проблема:

В некоторых конфигурациях PHP (например, при выключенной директиве filter.default) filter_input может вернуть пустую строку вместо NULL. Рекомендуется дополнительно проверять длину или сравнивать с пустой строкой.

Как определить метод через getenv?

Переменные окружения, устанавливаемые веб-сервером, также доступны через функцию getenv(). Однако этот способ менее надёжен, так как не все серверы передают REQUEST_METHOD в окружение, а в некоторых SAPI (например, FastCGI) переменная может отсутствовать.

<?php
$method = getenv('REQUEST_METHOD');
if ($method === false) {
    $method = 'GET'; // запасной вариант
}
echo $method;
?>

Используется в случаях, когда прямой доступ к $_SERVER невозможен или код выполняется в нестандартном окружении.

Типичная ошибка:

Путаница между getenv и $_ENV. Массив $_ENV может не заполняться при настройке variables_order в php.ini, поэтому полагаться только на него не стоит.

Как обработать методы PUT, DELETE и PATCH, если они передаются через POST с полем _method?

Некоторые фреймворки и клиенты (например, Laravel, Symfony) эмулируют методы PUT, DELETE и PATCH, отправляя форму с методом POST и скрытым полем _method. В таком случае реальный метод определяется не из $_SERVER['REQUEST_METHOD'], а из пользовательских данных.

<?php
$realMethod = $_SERVER['REQUEST_METHOD'];
if ($realMethod === 'POST') {
    $emulated = $_POST['_method'] ?? null;
    if ($emulated !== null && in_array(strtoupper($emulated), ['PUT', 'DELETE', 'PATCH', 'OPTIONS'])) {
        $realMethod = strtoupper($emulated);
    }
}
echo $realMethod;
?>

Этот подход позволяет использовать HTML-формы для RESTful запросов. Необходимо проверять, что значение поля _method допустимо, иначе возможна подмена метода.

Проблема безопасности:

Если не проверять разрешённые методы, злоумышленник может подставить произвольный метод. Рекомендуется использовать белый список разрешённых значений. Также следует помнить, что многие фреймворки автоматически проверяют подпись или токен для защиты от подделки межсайтовых запросов (CSRF).

Как получить метод при использовании php://input для нестандартных методов?

В исключительных ситуациях (например, при создании прокси-скрипта) метод может быть передан в теле запроса или в заголовке X-HTTP-Method-Override. Обработка такого сценария требует чтения заголовков или тела запроса.

<?php
// Чтение заголовка X-HTTP-Method-Override
$headerMethod = $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] ?? null;
// Если заголовок присутствует и разрешён, используем его
if ($headerMethod && in_array(strtoupper($headerMethod), ['PUT', 'DELETE', 'PATCH'])) {
    $method = strtoupper($headerMethod);
} else {
    $method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
}
echo $method;
?>

Этот способ часто применяется в клиентах, которые не могут напрямую отправить запрос с нужным методом (например, из JavaScript при ограничениях CORS). Однако заголовок должен быть явно установлен клиентом.

Типичная ошибка:

Забывать удалить дублирующуюся проверку: если $_SERVER['REQUEST_METHOD'] уже содержит PUT, то переопределение из заголовка может привести к путанице. Логичнее переопределять только при условии, что текущий метод равен POST.

Расширенные примеры определения HTTP метода в PHP

Пример 1. Полный обработчик запросов с проверкой метода и возвратом JSON

Пример
<?php
// Определение метода с поддержкой эмуляции через _method
$method = $_SERVER['REQUEST_METHOD'];
if ($method === 'POST' && isset($_POST['_method'])) {
    $allowed = ['PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD'];
    $override = strtoupper($_POST['_method']);
    if (in_array($override, $allowed)) {
        $method = $override;
    }
}

// Проверка валидности метода REST
$validMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD'];
if (!in_array($method, $validMethods)) {
    http_response_code(405);
    echo json_encode(['error' => 'Method not allowed']);
    exit;
}

// Обработка в зависимости от метода
switch ($method) {
    case 'GET':
        $response = ['message' => 'Данные получены'];
        break;
    case 'POST':
        $response = ['message' => 'Ресурс создан'];
        break;
    case 'PUT':
        // Чтение тела запроса
        $input = json_decode(file_get_contents('php://input'), true);
        $response = ['message' => 'Ресурс обновлён', 'data' => $input];
        break;
    case 'DELETE':
        $response = ['message' => 'Ресурс удалён'];
        break;
    default:
        $response = ['message' => 'Метод обработан'];
}

header('Content-Type: application/json; charset=utf-8');
echo json_encode($response, JSON_UNESCAPED_UNICODE);
?>

Результат при GET запросе:

{"message":"Данные получены"}

Пример 2. Использование filter_input с валидацией списка методов

Пример
<?php
$rawMethod = filter_input(INPUT_SERVER, 'REQUEST_METHOD', FILTER_SANITIZE_STRING);
if ($rawMethod === null || $rawMethod === false || $rawMethod === '') {
    $rawMethod = 'GET';
}
$allowed = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'CONNECT', 'TRACE'];
$method = in_array(strtoupper($rawMethod), $allowed) ? strtoupper($rawMethod) : 'GET';
echo 'Определённый метод: ' . $method;
?>

Код проверяет, что полученное значение входит в разрешённый список. Если нет - используется GET по умолчанию.

Пример 3. Тестирование с помощью cURL

Для проверки работы скрипта можно отправить запросы разными методами из командной строки:

Пример
curl -X GET http://example.com/script.php
curl -X POST http://example.com/script.php -d "_method=PUT"
curl -X PUT http://example.com/script.php -H "Content-Type: application/json" -d '{"name":"test"}'
curl -X DELETE http://example.com/script.php

Результат вывода для каждого запроса (при использовании обработчика из примера 1):

GET → {"message":"Данные получены"}
POST с _method=PUT → {"message":"Ресурс обновлён","data":{"_method":"PUT"}}
PUT → {"message":"Ресурс обновлён","data":{"name":"test"}}
DELETE → {"message":"Ресурс удалён"}

Пример 4. Определение метода в консольном PHP скрипте (CLI)

Пример
<?php
if (php_sapi_name() === 'cli') {
    // В CLI нет HTTP-запроса, метод можно задать аргументом
    $method = $argv[1] ?? 'GET';
    echo 'Метод из командной строки: ' . strtoupper($method) . PHP_EOL;
} else {
    $method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
    echo 'Метод из HTTP: ' . $method . PHP_EOL;
}
?>

Запуск: php script.php DELETE выведет Метод из командной строки: DELETE.

Пример 5. Обработка HEAD запроса (аналогичен GET, но без тела)

Пример
<?php
$method = $_SERVER['REQUEST_METHOD'];
if ($method === 'HEAD') {
    // Нужно установить те же заголовки, что и для GET, но не выводить тело
    header('Content-Length: 100');
    // ... установка других заголовков
    exit; // Не выводим тело
}
// для GET выводим тело
?>

Этот пример показывает, что для метода HEAD необходимо выставить все заголовки, как для GET, но не отправлять сам контент.

Пример 6. Получение метода из заголовка X-HTTP-Method-Override с эмуляцией через POST

Пример
<?php
$method = $_SERVER['REQUEST_METHOD'];
// Если текущий метод POST, проверяем заголовок переопределения
if ($method === 'POST' && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
    $override = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
    $allowedOverrides = ['PUT', 'DELETE', 'PATCH', 'OPTIONS'];
    if (in_array($override, $allowedOverrides)) {
        $method = $override;
    }
}
echo $method;
?>

Такой подход часто применяется в современных JavaScript фреймворках при использовании XMLHttpRequest с методом POST, когда нужно отправить PUT/DELETE.

определение HTTP метода в PHP - comments

En
Php http method (php)