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
.