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/uk/?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
Повертає всі cookies.
$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: uk,en-us;q=0.8,en;q=0.5,sl;q=0.3
$langs = ['hu', 'pl', 'uk']; // мови, підтримувані програмою
echo $httpRequest->detectLanguage($langs); // uk
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)
Переміщує завантажений файл у нове місце. Якщо цільовий файл вже існує, він буде перезаписаний.
$file->move('/path/to/files/name.ext');
getContents(): ?string
Повертає вміст завантаженого файлу. У випадку, якщо завантаження не
було успішним, повертає null
.
getContentType(): ?string
Визначає MIME content type завантаженого файлу на основі його сигнатури. У
випадку, якщо завантаження не було успішним або визначення не вдалося,
повертає null
.
Вимагає PHP-розширення fileinfo
.
getUntrustedName(): string
Повертає оригінальну назву файлу, як її надіслав браузер.
Не довіряйте значенню, повернутому цим методом. Клієнт міг надіслати шкідливу назву файлу з наміром пошкодити або зламати вашу програму.
getSanitizedName(): string
Повертає санітизовану назву файлу. Містить лише 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
.