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.

версія: 4.0