HTTP-запрос

Nette инкапсулирует HTTP-запрос в объекты с понятным API и одновременно предоставляет санитайзирующий фильтр.

HTTP-запрос представляет собой объект Nette\Http\Request. Если вы работаете с Nette, этот объект автоматически создается фреймворком, и вы можете получить его с помощью внедрения зависимостей. В презентерах достаточно просто вызвать метод $this->getHttpRequest(). Если вы работаете вне Nette Framework, вы можете создать объект с помощью RequestFactory.

Большим преимуществом Nette является то, что при создании объекта он автоматически очищает все входные параметры GET, POST, COOKIE, а также URL от управляющих символов и невалидных UTF-8 последовательностей. С этими данными затем можно безопасно работать дальше. Очищенные данные впоследствии используются в презентерах и формах.

Установка и требования

Nette\Http\Request

Этот объект является immutable (неизменяемым). У него нет сеттеров, есть только один так называемый wither withUrl(), который не изменяет объект, а возвращает новый экземпляр с измененным значением.

withUrl (Nette\Http\UrlScript $url): Nette\Http\Request

Возвращает клон с другим URL.

getUrl(): Nette\Http\UrlScript

Возвращает URL запроса как объект UrlScript.

$url = $httpRequest->getUrl();
echo $url; // https://doc.nette.org/cs/?action=edit
echo $url->getHost(); // nette.org

Внимание: браузеры не отправляют фрагмент на сервер, поэтому $url->getFragment() будет возвращать пустую строку.

getQuery (?string $key=null): string|array|null

Возвращает параметры GET-запроса.

$all = $httpRequest->getQuery(); // возвращает массив всех параметров из URL
$id = $httpRequest->getQuery('id'); // возвращает GET-параметр 'id' (или null)

getPost (?string $key=null): string|array|null

Возвращает параметры POST-запроса.

$all = $httpRequest->getPost(); // возвращает массив всех параметров из POST
$id = $httpRequest->getPost('id'); // возвращает POST-параметр 'id' (или null)

getFile (string|string[] $key): Nette\Http\FileUpload|array|null

Возвращает загруженный файл как объект Nette\Http\FileUpload:

$file = $httpRequest->getFile('avatar');
if ($file?->hasFile()) { // был ли загружен какой-либо файл?
	$file->getUntrustedName(); // имя файла, отправленное пользователем
	$file->getSanitizedName(); // имя без опасных символов
}

Для доступа к вложенной структуре укажите массив ключей.

//<input type="file" name="my-form[details][avatar]" multiple>
$file = $request->getFile(['my-form', 'details', 'avatar']);

Поскольку нельзя доверять данным извне и, следовательно, полагаться на структуру файлов, этот способ безопаснее, чем, например, $request->getFiles()['my-form']['details']['avatar'], который может не сработать.

getFiles(): array

Возвращает дерево всех загруженных файлов в нормализованной структуре, листьями которой являются объекты Nette\Http\FileUpload:

$files = $httpRequest->getFiles();

getCookie (string $key): string|array|null

Возвращает cookie или null, если она не существует.

$sessId = $httpRequest->getCookie('sess_id');

getCookies(): array

Возвращает все cookie.

$cookies = $httpRequest->getCookies();

getMethod(): string

Возвращает HTTP-метод, с которым был сделан запрос.

$httpRequest->getMethod(); // GET, POST, HEAD, PUT

isMethod (string $method)bool

Проверяет HTTP-метод, с которым был сделан запрос. Параметр нечувствителен к регистру.

if ($httpRequest->isMethod('GET')) // ...

getHeader (string $header): ?string

Возвращает HTTP-заголовок или null, если он не существует. Параметр нечувствителен к регистру.

$userAgent = $httpRequest->getHeader('User-Agent');

getHeaders(): array

Возвращает все HTTP-заголовки как ассоциативный массив.

$headers = $httpRequest->getHeaders();
echo $headers['Content-Type'];

isSecured(): bool

Является ли соединение шифрованным (HTTPS)? Для правильной работы может потребоваться настроить прокси.

isSameSite(): bool

Приходит ли запрос с того же (суб)домена и инициирован ли он кликом по ссылке? Nette для обнаружения использует cookie _nss (ранее nette-samesite).

isAjax(): bool

Является ли это AJAX-запросом?

getRemoteAddress(): ?string

Возвращает IP-адрес пользователя. Для правильной работы может потребоваться настроить прокси.

getRemoteHost(): ?string

Возвращает DNS-преобразование IP-адреса пользователя. Для правильной работы может потребоваться настроить прокси.

getBasicCredentials(): ?array

Возвращает учетные данные для Basic HTTP authentication.

[$user, $password] = $httpRequest->getBasicCredentials();

getRawBody(): ?string

Возвращает тело HTTP-запроса.

$body = $httpRequest->getRawBody();

detectLanguage (array $langs): ?string

Определяет язык. В качестве параметра $langs передаем массив языков, которые поддерживает приложение, и она возвращает тот, который предпочел бы видеть браузер посетителя. Это не магия, просто используется заголовок Accept-Language. Если совпадений нет, возвращает null.

// браузер отправляет, например, Accept-Language: cs,en-us;q=0.8,en;q=0.5,sl;q=0.3

$langs = ['hu', 'pl', 'en']; // языки, поддерживаемые приложением
echo $httpRequest->detectLanguage($langs); // en

RequestFactory

Класс Nette\Http\RequestFactory служит для создания экземпляра Nette\Http\Request, который представляет текущий HTTP-запрос. (Если вы работаете с Nette, объект HTTP-запроса автоматически создается фреймворком.)

$factory = new Nette\Http\RequestFactory;
$httpRequest = $factory->fromGlobals();

Метод fromGlobals() создает объект запроса на основе текущих глобальных переменных PHP ($_GET, $_POST, $_COOKIE, $_FILES и $_SERVER). При создании объекта он автоматически очищает все входные параметры GET, POST, COOKIE, а также URL от управляющих символов и невалидных UTF-8 последовательностей, что обеспечивает безопасность при дальнейшей работе с этими данными.

RequestFactory можно сконфигурировать перед вызовом fromGlobals():

  • методом $factory->setBinary() отключите автоматическую очистку входных параметров от управляющих символов и невалидных UTF-8 последовательностей.
  • методом $factory->setProxy(...) укажите IP-адрес прокси-сервера, что необходимо для правильного определения IP-адреса пользователя.

RequestFactory позволяет определить фильтры, которые автоматически трансформируют части URL запроса. Эти фильтры удаляют нежелательные символы из URL, которые могут быть туда вставлены, например, из-за неправильной реализации систем комментариев на различных веб-сайтах:

// удаление пробелов из пути
$requestFactory->urlFilters['path']['%20'] = '';

// удаление точки, запятой или правой скобки с конца URI
$requestFactory->urlFilters['url']['[.,)]$'] = '';

// очистка пути от удвоенных слешей (фильтр по умолчанию)
$requestFactory->urlFilters['path']['/{2,}'] = '/';

Первый ключ 'path' или 'url' определяет, к какой части URL применяется фильтр. Второй ключ — это регулярное выражение, которое нужно найти, а значение — это замена, которая будет использована вместо найденного текста.

Загруженные файлы

Метод Nette\Http\Request::getFiles() возвращает массив всех загруженных файлов в нормализованной структуре, листьями которой являются объекты Nette\Http\FileUpload. Они инкапсулируют данные, отправленные элементом формы <input type=file>.

Структура отражает именование элементов в HTML. В простейшем случае это может быть единственный именованный элемент формы, отправленный как:

<input type="file" name="avatar">

В этом случае $request->getFiles() возвращает массив:

[
	'avatar' => /* FileUpload instance */
]

Объект FileUpload создается и в случае, если пользователь не отправил ни одного файла или отправка не удалась. Был ли файл отправлен, возвращает метод hasFile():

$request->getFile('avatar')?->hasFile();

В случае имени элемента, использующего нотацию для массива:

<input type="file" name="my-form[details][avatar]">

возвращаемое дерево выглядит так:

[
	'my-form' => [
		'details' => [
			'avatar' => /* FileUpload instance */
		],
	],
]

Можно создать и массив файлов:

<input type="file" name="my-form[details][avatars][]" multiple>

В таком случае структура выглядит так:

[
	'my-form' => [
		'details' => [
			'avatars' => [
				0 => /* FileUpload instance */,
				1 => /* FileUpload instance */,
				2 => /* FileUpload instance */,
			],
		],
	],
]

Доступ к индексу 1 вложенного массива лучше всего получить так:

$file = $request->getFile(['my-form', 'details', 'avatars', 1]);
if ($file instanceof FileUpload) {
	// ...
}

Поскольку нельзя доверять данным извне и, следовательно, полагаться на структуру файлов, этот способ безопаснее, чем, например, $request->getFiles()['my-form']['details']['avatars'][1], который может не сработать.

Обзор методов FileUpload

hasFile(): bool

Возвращает true, если пользователь загрузил какой-либо файл.

isOk(): bool

Возвращает true, если файл был загружен успешно.

getError(): int

Возвращает код ошибки при загрузке файла. Это одна из констант UPLOAD_ERR_XXX. В случае, если загрузка прошла успешно, возвращает UPLOAD_ERR_OK.

move (string $dest): void

Перемещает загруженный файл в новое местоположение. Если целевой файл уже существует, он будет перезаписан.

$file->move('/path/to/files/name.ext');

getContents(): ?string

Возвращает содержимое загруженного файла. В случае, если загрузка не была успешной, возвращает null.

getContentType(): ?string

Определяет MIME content type загруженного файла на основе его сигнатуры. В случае, если загрузка не была успешной или определение не удалось, возвращает null.

Требует PHP-расширение fileinfo.

getUntrustedName(): string

Возвращает оригинальное имя файла, как его отправил браузер.

Не доверяйте значению, возвращаемому этим методом. Клиент мог отправить вредоносное имя файла с намерением повредить или взломать ваше приложение.

getSanitizedName(): string

Возвращает очищенное (sanitized) имя файла. Содержит только ASCII-символы [a-zA-Z0-9.-]. Если имя не содержит таких символов, возвращает 'unknown'. Если файл является изображением в формате JPEG, PNG, GIF, WebP или AVIF, возвращает и правильное расширение.

Требует PHP-расширение fileinfo.

getSuggestedExtension(): ?string

Возвращает подходящее расширение файла (без точки), соответствующее определенному MIME-типу.

Требует PHP-расширение fileinfo.

getUntrustedFullPath(): string

Возвращает оригинальный путь к файлу, как его отправил браузер при загрузке папки. Полный путь доступен только в PHP 8.1 и выше. В предыдущих версиях этот метод возвращает оригинальное имя файла.

Не доверяйте значению, возвращаемому этим методом. Клиент мог отправить вредоносное имя файла с намерением повредить или взломать ваше приложение.

getSize(): int

Возвращает размер загруженного файла. В случае, если загрузка не была успешной, возвращает 0.

getTemporaryFile(): string

Возвращает путь к временному местоположению загруженного файла. В случае, если загрузка не была успешной, возвращает ''.

isImage(): bool

Возвращает true, если загруженный файл является изображением в формате JPEG, PNG, GIF, WebP или AVIF. Определение происходит на основе его сигнатуры и не проверяется целостность всего файла. Не повреждено ли изображение, можно узнать, например, попытавшись его загрузить.

Требует PHP-расширение fileinfo.

getImageSize(): ?array

Возвращает пару [ширина, высота] с размерами загруженного изображения. В случае, если загрузка не была успешной или это не валидное изображение, возвращает null.

toImage(): Nette\Utils\Image

Загружает изображение как объект Image. В случае, если загрузка не была успешной или это не валидное изображение, выбрасывает исключение Nette\Utils\ImageException.

версия: 4.0