Żądanie HTTP

Nette enkapsuluje żądanie HTTP w obiekty o zrozumiałym API, zapewniając jednocześnie filtr sanityzujący.

Żądanie HTTP jest reprezentowane przez obiekt Nette\Http\Request, do którego uzyskujesz dostęp poprzez przekazanie go za pomocą zastrzyku zależności. W presenterech wystarczy zadzwonić na $httpRequest = $this->getHttpRequest().

Co ważne, gdy Nette tworzy ten obiekt, sanityzuje wszystkie parametry wejściowe GET, POST, COOKIE, a także URL ze znaków sterujących i nieprawidłowych sekwencji UTF-8. Można więc wtedy bezpiecznie kontynuować pracę z danymi. Oczyszczone dane są następnie wykorzystywane w prezenterach i formularzach.

Instalacja i wymagania

Nette\NRequest

Ten obiekt jest niezmienny. Nie posiada żadnych seterów, ma tylko jeden tzw. wither withUrl(), który nie modyfikuje obiektu, ale zwraca nową instancję ze zmienioną wartością.

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

Zwraca klon z innym adresem URL.

getUrl(): Nette\Http\UrlScript

Zwraca adres URL żądania jako obiekt UrlScript.

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

Przeglądarki nie wysyłają fragmentu do serwera, więc $url->getFragment() zwróci pusty ciąg.

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

Zwraca parametry żądania GET.

$all = $httpRequest->getQuery(); // zwraca tablicę wszystkich parametrów z adresu URL
$id = $httpRequest->getQuery('id'); // zwraca parametr GET 'id' (lub null)

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

Zwraca parametry żądania POST.

$all = $httpRequest->getPost(); // zwraca tablicę wszystkich parametrów z POSTa
$id = $httpRequest->getPost('id'); // zwraca parametr POST 'id' (lub null)

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

Zwraca przesłanie jako obiekt Nette\Http\FileUpload:

$file = $httpRequest->getFile('avatar');
if ($file->hasFile()) { // czy jakiś plik został przesłany?
	$file->getUntrustedName(); // nazwa pliku przesłanego przez użytkownika
	$file->getSanitizedName(); // nazwa bez niebezpiecznych znaków
}

Określenie pola kluczowego dla dostępu do struktury zagnieżdżonej.

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

Ponieważ nie można ufać zewnętrznym danym, a zatem nie można polegać na formie struktury plików, jest to bezpieczniejsza metoda niż np. $request->getFiles()['my-form']['details']['avatar']co może się nie udać.

getFiles(): array

Zwraca drzewo wszystkich uploadów w znormalizowanej strukturze, której liście są obiektami Nette\Http\FileUpload:

$files = $httpRequest->getFiles();

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

Zwraca cookie lub null, jeśli nie istnieje.

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

getCookies(): array

Zwraca wszystkie ciasteczka.

$cookies = $httpRequest->getCookies();

getMethod(): string

Zwraca metodę HTTP, za pomocą której zostało wykonane żądanie.

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

isMethod(string $method)bool

Testuje metodę HTTP, za pomocą której zostało wykonane żądanie. Wielkość liter w parametrze nie ma znaczenia.

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

getHeader(string $header): ?string

Zwraca nagłówek HTTP lub null, jeśli nie istnieje. Wielkość liter w parametrze nie ma znaczenia.

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

getHeaders(): array

Zwraca wszystkie nagłówki HTTP jako tablicę asocjacyjną.

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

isSecured(): bool

Czy połączenie jest szyfrowane (HTTPS)? Może być konieczne skonfigurowanie proxy dla prawidłowej funkcjonalności.

isSameSite(): bool

Czy żądanie pochodzi z tej samej (pod)domeny i jest inicjowane przez kliknięcie na link? Nette używa pliku cookie _nss (dawniej nette-samesite), aby to wykryć.

isAjax(): bool

Czy to jest żądanie AJAX?

getRemoteAddress(): ?string

Zwraca adres IP użytkownika. Może być konieczne skonfigurowanie proxy dla prawidłowej funkcjonalności.

getRemoteHost(): ?string

Zwraca rozdzielczość DNS adresu IP użytkownika. Może być konieczne skonfigurowanie proxy dla prawidłowej funkcjonalności.

getBasicCredentials(): ?string

Zwraca dane uwierzytelniające dla uwierzytelniania Basic HTTP.

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

getRawBody(): ?string

Zwraca treść żądania HTTP.

$body = $httpRequest->getRawBody();

detectLanguage(array $langs): ?string

Wykrywa język. Przekaż tablicę języków obsługiwanych przez aplikację jako parametr $lang, a zwróci ona ten, który przeglądarka odwiedzającego wolałaby zobaczyć. Nie ma w tym żadnej magii, po prostu używa nagłówka Accept-Language. Jeśli nie ma dopasowania, zwraca null.

// przeglądarka wysyła np. Accept-Language: en-us;q=0.8,en;q=0.5,en;q=0.3

$langs = ['hu', 'pl', 'en']; // języki obsługiwane przez aplikację
echo $httpRequest->detectLanguage($langs); // pl

RequestFactory

Bieżący obiekt żądania HTTP wytworzy Nette\Http\RequestFactory. Jeśli piszesz aplikację, która nie używa kontenera DI, wytworzysz żądanie w następujący sposób:

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

RequestFactory może być skonfigurowany przed wywołaniem fromGlobals(). Możemy wyłączyć sanityzację parametrów wejściowych ze znaków sterujących i nieprawidłowych sekwencji UTF-8 za pomocą $factory->setBinary(). A także skonfigurować serwer proxy za pomocą $factory->setProxy(...), co jest ważne dla prawidłowego wykrywania adresu IP użytkownika.

Za pomocą tzw. filtrów można oczyścić adres URL ze znaków, które mogą się do niego dostać, np. z powodu źle wdrożonych systemów komentarzy na różnych zagranicznych stronach:

// usuń spacje z drogi
$requestFactory->urlFilters['path']['%20'] = '';

// usuń kropkę, przecinek lub prawy nawias z końca URI
$requestFactory->urlFilters['url']['[.,)]$'] = '';

// czyszczenie ścieżki z podwójnych ukośników (domyślny filtr)
$requestFactory->urlFilters['path']['/{2,}'] = '/';

Przesłane pliki

Metoda Nette\Http\Request::getFiles() zwraca tablicę wszystkich uploadów w znormalizowanej strukturze, której listki są obiektami Nette\Http\FileUpload. Zawierają one dane przesłane przez element formularza <input type=file>.

Struktura odzwierciedla nazewnictwo elementów w HTML. W najprostszym przypadku może to być pojedynczy nazwany element formularza złożony jako:

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

W tym przypadku $request->getFiles() zwraca tablicę:

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

Obiekt FileUpload jest tworzony nawet jeśli użytkownik nie przesłał żadnego pliku lub przesłanie nie powiodło się. Jeśli plik został załadowany, to zwraca się metoda hasFile():

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

W przypadku nazwy elementu z wykorzystaniem notacji tablicowej:

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

zwrócone drzewo wygląda tak:

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

Można również utworzyć tablicę plików:

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

W tym przypadku struktura wygląda tak:

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

Najlepszym sposobem podejścia do indeksu 1 zagnieżdżonej tablicy jest następujący sposób:

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

Ponieważ nie można ufać zewnętrznym danym, a zatem nie można polegać na formie struktury plików, jest to bezpieczniejszy sposób niż np. $request->getFiles()['my-form']['details']['avatars'][1]co może się nie udać.

Przegląd metod FileUpload

hasFile(): bool

Zwraca true, jeśli użytkownik przesłał plik.

isOk(): bool

Zwraca true, jeśli plik został przesłany pomyślnie.

getError(): int

Zwraca kod błędu podczas przesyłania pliku. Jest to jedna ze stałych UPLOAD_ERR_XXX. Jeśli przesyłanie zakończyło się sukcesem, zwraca UPLOAD_ERR_OK.

move(string $dest)

Przenosi przesłany plik do nowej lokalizacji. Jeśli plik docelowy już istnieje, zostanie on nadpisany.

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

getContents(): ?string

Zwraca zawartość przesłanego pliku. Jeśli przesłanie nie powiodło się, zwraca null.

getContentType(): ?string

Wykrywa typ zawartości MIME przesłanego pliku na podstawie jego sygnatury. Jeśli przesłanie nie powiodło się lub wykrycie nie powiodło się, zwraca null.

Wymaga rozszerzenia PHP fileinfo.

getUntrustedName(): string

Zwraca oryginalną nazwę pliku przesłaną przez przeglądarkę.

Nie należy ufać wartości zwracanej przez tę metodę. Klient mógł wysłać złośliwą nazwę pliku z zamiarem uszkodzenia lub zhakowania Twojej aplikacji.

getSanitizedName(): string

Zwraca oczyszczoną nazwę pliku. Zawiera tylko znaki ASCII [a-zA-Z0-9.-]. Jeśli nazwa nie zawiera takich znaków, zwraca 'unknown'. Jeśli plik jest obrazem JPEG, PNG, GIF lub WebP, zwraca również prawidłowe rozszerzenie.

Wymaga rozszerzenia PHP fileinfo.

getSuggestedExtension(): ?string

Zwraca odpowiednie rozszerzenie pliku (bez kropki) odpowiadające wykrytemu typowi MIME.

Wymaga rozszerzenia PHP fileinfo.

getUntrustedFullPath(): string

Zwraca oryginalną ścieżkę pliku, jak wysłane przez przeglądarkę, gdy folder został załadowany. Pełna ścieżka jest dostępna tylko w PHP 8.1 i wyższych. W poprzednich wersjach metoda ta zwracała oryginalną nazwę pliku.

Nie należy ufać wartości zwracanej przez tę metodę. Klient mógł wysłać złośliwą nazwę pliku z zamiarem uszkodzenia lub zhakowania Twojej aplikacji.

getSize(): int

Zwraca rozmiar przesłanego pliku. Zwraca 0 jeśli załadowanie nie powiodło się.

getTemporaryFile(): string

Zwraca ścieżkę do tymczasowej lokalizacji przesłanego pliku. Jeśli przesłanie nie powiodło się, zwraca ''.

isImage(): bool

Zwraca true, jeśli przesłany plik jest obrazem JPEG, PNG, GIF lub WebP. Wykrywanie oparte jest na jego sygnaturze i nie sprawdza integralności całego pliku. Możliwe jest określenie, czy obraz jest uszkodzony, na przykład próbując go załadować.

Wymaga rozszerzenia PHP fileinfo.

getImageSize(): ?array

Zwraca parę [šířka, výška] z wymiarami przesłanego obrazu. Jeśli przesłanie nie powiodło się lub nie jest to prawidłowy obraz, zwraca null.

toImage(): Nette\Utils\Image

Wczytuje obraz jako obiekt Image. Jeśli przesłanie nie powiodło się lub nie jest prawidłowym obrazem, rzuca wyjątek Nette\Utils\ImageException.

wersja: 4.0