HTTP заявка

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

HTTP заявката представлява обект Nette\Http\Request. Ако работите с Nette, този обект се създава автоматично от framework-а и можете да го получите чрез dependency injection. В презентерите е достатъчно само да извикате метода $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

Връща бисквитка или null, когато не съществува.

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

getCookies(): array

Връща всички бисквитки.

$cookies = $httpRequest->getCookies();

getMethod(): string

Връща HTTP метода, с който е направена заявката.

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

isMethod (string $method)bool

Тества HTTP метода, с който е направена заявката. Параметърът е case-insensitive.

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

getHeader (string $header): ?string

Връща HTTP хедър или null, ако не съществува. Параметърът е case-insensitive.

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

getHeaders(): array

Връща всички HTTP хедъри като асоциативен масив.

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

isSecured(): bool

Връзката шифрована ли е (HTTPS)? За правилната функционалност може да е необходимо да се настрои прокси.

isSameSite(): bool

Заявката идва ли от същия (под)домейн и е инициирана чрез кликване върху връзка? Nette използва бисквитката _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

Открива езика. Като параметър $lang предаваме масив с езиците, които приложението поддържа, и тя връща този, който браузърът на посетителя би предпочел най-много. Това не са никакви магии, просто се използва хедърът 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 заявката се създава автоматично от framework-а.)

$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