HTTP-Request

Nette kapselt den HTTP-Request in Objekte mit einer klaren API und stellt zugleich einen Filter zur Bereinigung der Eingaben bereit.

Der HTTP-Request wird durch das Objekt Nette\Http\Request repräsentiert. Wenn Sie mit Nette arbeiten, wird dieses Objekt automatisch vom Framework erzeugt, und Sie können es sich per Dependency Injection übergeben lassen. In Presentern genügt der Aufruf der Methode $this->getHttpRequest(). Wenn Sie außerhalb des Nette Frameworks arbeiten, können Sie das Objekt mit der RequestFactory erzeugen.

Ein großer Vorteil von Nette ist, dass es beim Erzeugen des Objekts automatisch alle Eingabeparameter (GET, POST, COOKIE) sowie die URL bereinigt und Steuerzeichen und ungültige UTF-8-Sequenzen entfernt. Mit diesen Daten können Sie dann sicher arbeiten. Die bereinigten Daten werden anschließend in Presentern und Formularen verwendet.

Installation und Anforderungen

Nette\Http\Request

Dieses Objekt ist unveränderlich. Es hat keine Setter; es hat nur einen sogenannten Wither, withUrl(), der das Objekt nicht verändert, sondern eine neue Instanz mit dem geänderten Wert zurückgibt.

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

Gibt einen Klon mit einer anderen URL zurück.

getUrl(): Nette\Http\UrlScript

Gibt die URL des Requests als Objekt UrlScript zurück.

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

Achtung: Browser senden das Fragment nicht an den Server, $url->getFragment() gibt also einen leeren String zurück.

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

Gibt die Parameter des GET-Requests zurück.

$all = $httpRequest->getQuery();    // Array aller URL-Parameter
$id = $httpRequest->getQuery('id'); // gibt den GET-Parameter 'id' zurück (oder null)

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

Gibt die Parameter des POST-Requests zurück.

$all = $httpRequest->getPost();     // Array aller POST-Parameter
$id = $httpRequest->getPost('id');  // gibt den POST-Parameter 'id' zurück (oder null)

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

Gibt einen Upload als Objekt Nette\Http\FileUpload zurück:

$file = $httpRequest->getFile('avatar');
if ($file?->hasFile()) { // wurde überhaupt eine Datei hochgeladen?
	$file->getUntrustedName(); // vom Benutzer gesendeter Dateiname
	$file->getSanitizedName(); // Name ohne gefährliche Zeichen
}

Um auf eine verschachtelte Struktur zuzugreifen, geben Sie ein Array von Schlüsseln an.

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

Weil Sie externen Daten nicht trauen können und sich deshalb nicht auf die Struktur der Dateien verlassen dürfen, ist dieser Weg sicherer als zum Beispiel $request->getFiles()['my-form']['details']['avatar'], das fehlschlagen könnte.

getFiles(): array

Gibt einen Baum aller Uploads in einer normalisierten Struktur zurück, deren Blätter Objekte vom Typ Nette\Http\FileUpload sind:

$files = $httpRequest->getFiles();

getCookie (string $key): ?string

Gibt ein Cookie zurück oder null, wenn es nicht existiert.

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

getCookies(): array

Gibt alle Cookies zurück.

$cookies = $httpRequest->getCookies();

getMethod(): string

Gibt die HTTP-Methode zurück, mit der der Request gestellt wurde.

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

isMethod (string $method)bool

Prüft die HTTP-Methode, mit der der Request gestellt wurde. Beim Parameter wird die Groß- und Kleinschreibung nicht unterschieden.

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

getHeader (string $header): ?string

Gibt einen HTTP-Header zurück oder null, wenn er nicht existiert. Beim Parameter wird die Groß- und Kleinschreibung nicht unterschieden.

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

getHeaders(): array<string, string>

Gibt alle HTTP-Header als assoziatives Array zurück. Die Schlüssel sind auf Kleinbuchstaben normalisiert.

$headers = $httpRequest->getHeaders();
echo $headers['content-type'];

isSecured(): bool

Ist die Verbindung verschlüsselt (HTTPS)? Für das korrekte Funktionieren kann die Einrichtung eines Proxys nötig sein.

isSameSite(): bool

Kam der Request von derselben Site? Seit Version 3.4 wird sie durch das leistungsfähigere isFrom() ersetzt.

isFrom (FetchSite|array $site, FetchDest|array|null $dest=null, ?bool $user=null)bool

Sagt Ihnen, woher der Request kam und wie der Browser ihn gestellt hat, und zwar anhand der Sec-Fetch-*-Header (der sogenannten Fetch Metadata), die der Browser selbst setzt und die eine im Browser des Opfers laufende Seite weder fälschen noch entfernen kann. Nette nutzt das intern, um Formulare und Signale automatisch gegen Cross-Site Request Forgery (CSRF) zu schützen. Nützlich ist es, wenn Sie eigene sensible Aktionen absichern wollen, etwa API-Endpunkte oder destruktive Links.

Die Methode gibt nur dann true zurück, wenn der Request alle von Ihnen angegebenen Bedingungen erfüllt. Der erste Parameter $site beschreibt die Beziehung zwischen der Seite, die den Request ausgelöst hat, und Ihrer Site (der Header Sec-Fetch-Site). Er nimmt einen einzelnen Wert oder eine Liste dieser FetchSite-Fälle entgegen:

  • FetchSite::SameOrigin – vom exakt selben Origin (Schema, Host und Port)
  • FetchSite::SameSite – von derselben Site, eventuell einer anderen Subdomain
  • FetchSite::CrossSite – von einer fremden Site
  • FetchSite::None – der Benutzer hat ihn direkt ausgelöst, z. B. durch Eingabe der URL oder Öffnen eines Lesezeichens
// stammt der Request von unseren eigenen Seiten?
if (!$httpRequest->isFrom([FetchSite::SameOrigin, FetchSite::SameSite])) {
	// die Aktion blockieren
}

Der optionale Parameter $dest (der Header Sec-Fetch-Dest) sagt, welche Art von Ressource der Browser lädt, z. B. FetchDest::Document für eine Navigation auf oberster Ebene oder FetchDest::Empty für einen aus JavaScript gestellten Request. Der optionale Parameter $user (der Header Sec-Fetch-User) gibt an, ob die Navigation durch eine echte Benutzeraktion wie den Klick auf einen Link oder das Absenden eines Formulars ausgelöst wurde; übergeben Sie true, um das zu verlangen.

Eine Prüfung, dass eine Aktion nur von Ihren eigenen Seiten und nur durch eine echte Benutzeraktion erreichbar ist, sieht dann so aus:

if (!$httpRequest->isFrom(FetchSite::SameOrigin, FetchDest::Document, user: true)) {
	$this->error();
}

Ältere Browser (Safari vor 16.4) senden die Sec-Fetch-*-Header nicht. Für sie greift Nette auf ein SameSite=Strict-Cookie zurück, das nur belegt, dass der Request nicht Cross-Site ist. Eine Prüfung, die zusätzlich $dest oder $user verlangt, lässt sich auf diese Weise nicht bestätigen und gibt in diesen Browsern false zurück – wenn das zu streng ist, prüfen Sie nur $site.

isAjax(): bool

Handelt es sich um einen AJAX-Request?

getRemoteAddress(): ?string

Gibt die IP-Adresse des Benutzers zurück. Für das korrekte Funktionieren kann die Einrichtung eines Proxys nötig sein.

getRemoteHost(): ?string

Veraltet, gibt immer null zurück. Reverse-DNS-Abfragen waren langsam und unzuverlässig; wenn Sie den Hostnamen brauchen, ermitteln Sie ihn selbst aus getRemoteAddress().

getBasicCredentials(): ?array

Gibt die Zugangsdaten für die HTTP-Basic-Authentifizierung zurück.

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

getRawBody(): ?string

Gibt den Body des HTTP-Requests zurück.

$body = $httpRequest->getRawBody();

getOrigin(): ?UrlImmutable

Gibt den Origin zurück, von dem der Request kam. Ein Origin besteht aus Schema (Protokoll), Hostname und Port – zum Beispiel https://example.com:8080. Gibt null zurück, wenn der Origin-Header fehlt oder auf 'null' gesetzt ist.

$origin = $httpRequest->getOrigin();
echo $origin; // https://example.com:8080
echo $origin?->getHost(); // example.com

Der Browser sendet den Header Origin in folgenden Fällen:

  • Cross-Origin-Requests (AJAX-Aufrufe an eine andere Domain)
  • POST-, PUT-, DELETE- und andere verändernde Requests
  • Requests über die Fetch API

Der Browser sendet den Header Origin NICHT bei:

  • gewöhnlichen GET-Requests an dieselbe Domain (Same-Origin-Navigation)
  • direkter Navigation durch Eingabe einer URL in die Adresszeile
  • Requests von Clients, die keine Browser sind

Anders als der Header Referer enthält Origin nur Schema, Host und Port – nicht den vollständigen Pfad der URL. Das macht ihn für Sicherheitsprüfungen geeigneter und wahrt zugleich die Privatsphäre der Benutzer. Der Header Origin wird vor allem für die Prüfung von CORS (Cross-Origin Resource Sharing) verwendet.

detectLanguage (array $langs): ?string

Erkennt die Sprache. Übergeben Sie als Parameter $langs ein Array der von der Anwendung unterstützten Sprachen, und die Methode gibt diejenige zurück, die der Browser des Besuchers bevorzugt. Das ist keine Magie, sie nutzt nur den Header Accept-Language. Wird keine Übereinstimmung gefunden, gibt sie null zurück.

// Der Browser sendet z. B. Accept-Language: cs,en-us;q=0.8,en;q=0.5,sl;q=0.3

$langs = ['hu', 'pl', 'en']; // von der Anwendung unterstützte Sprachen
echo $httpRequest->detectLanguage($langs); // en

RequestFactory

Die Klasse Nette\Http\RequestFactory dient dazu, eine Instanz von Nette\Http\Request zu erzeugen, die den aktuellen HTTP-Request repräsentiert. (Wenn Sie mit Nette arbeiten, wird das Objekt des HTTP-Requests automatisch vom Framework erzeugt.)

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

Die Methode fromGlobals() erzeugt das Request-Objekt anhand der aktuellen globalen Variablen von PHP ($_GET, $_POST, $_COOKIE, $_FILES und $_SERVER). Beim Erzeugen des Objekts bereinigt sie automatisch alle Eingabeparameter (GET, POST, COOKIE) sowie die URL von Steuerzeichen und ungültigen UTF-8-Sequenzen und sorgt so für Sicherheit bei der späteren Arbeit mit diesen Daten.

Die RequestFactory lässt sich vor dem Aufruf von fromGlobals() konfigurieren:

  • Die Methode $factory->setBinary() schaltet die automatische Bereinigung der Eingabeparameter von Steuerzeichen und ungültigen UTF-8-Sequenzen ab.
  • Die Methode $factory->setProxy(...) gibt die IP-Adresse des Proxyservers an, was für die korrekte Erkennung der IP-Adresse des Benutzers nötig ist.
  • Die Methode $factory->setForceHttps() .{data-version:3.3.4} erzwingt unabhängig von der Serverumgebung das Schema HTTPS für den Request.

Die RequestFactory erlaubt es, Filter zu definieren, die Teile der Request-URL automatisch umschreiben. Diese Filter entfernen unerwünschte Zeichen aus URLs, die zum Beispiel durch fehlerhafte Implementierungen von Kommentarsystemen auf verschiedenen Websites hineingeraten sein können:

// Leerzeichen aus dem Pfad entfernen
$requestFactory->urlFilters['path']['%20'] = '';

// Punkt, Komma oder schließende Klammer am Ende der URI entfernen
$requestFactory->urlFilters['url']['[.,)]$'] = '';

// den Pfad von doppelten Schrägstrichen bereinigen (Standardfilter)
$requestFactory->urlFilters['path']['/{2,}'] = '/';

Der erste Schlüssel, 'path' oder 'url', bestimmt, auf welchen Teil der URL der Filter angewendet wird. Der zweite Schlüssel ist der reguläre Ausdruck, nach dem gesucht wird, und der Wert ist der Ersatz, der anstelle des gefundenen Textes eingesetzt wird.

Hochgeladene Dateien

Die Methode Nette\Http\Request::getFiles() gibt ein Array aller Uploads in einer normalisierten Struktur zurück, deren Blätter Objekte vom Typ Nette\Http\FileUpload sind. Diese kapseln die Daten, die über das Formularelement <input type=file> gesendet wurden.

Die Struktur bildet die Benennung der Elemente im HTML ab. Im einfachsten Fall kann das ein einzelnes benanntes Formularelement sein, das so gesendet wird:

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

In diesem Fall gibt $request->getFiles() ein Array zurück:

[
	'avatar' => /* FileUpload-Instanz */
]

Das Objekt FileUpload wird auch dann erzeugt, wenn der Benutzer keine Datei hochgeladen hat oder der Upload fehlgeschlagen ist. Die Methode hasFile() gibt true zurück, wenn eine Datei gesendet wurde:

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

Bei einem Elementnamen in Array-Schreibweise:

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

sieht der zurückgegebene Baum so aus:

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

Sie können auch Arrays von Dateien erzeugen:

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

In einem solchen Fall sieht die Struktur so aus:

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

Am besten greifen Sie auf den Index 1 des verschachtelten Arrays so zu:

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

Weil Sie externen Daten nicht trauen können und sich deshalb nicht auf die Struktur der Dateien verlassen dürfen, ist dieser Weg sicherer als zum Beispiel $request->getFiles()['my-form']['details']['avatars'][1], das fehlschlagen könnte.

Übersicht der FileUpload-Methoden

hasFile(): bool

Gibt true zurück, wenn der Benutzer eine Datei hochgeladen hat.

isOk(): bool

Gibt true zurück, wenn die Datei erfolgreich hochgeladen wurde.

getError(): int

Gibt den Fehlercode zurück, der zur hochgeladenen Datei gehört. Es ist eine der Konstanten UPLOAD_ERR_XXX. Wurde die Datei erfolgreich hochgeladen, gibt sie UPLOAD_ERR_OK zurück.

move (string $dest)

Verschiebt eine hochgeladene Datei an einen neuen Ort. Existiert die Zieldatei bereits, wird sie überschrieben.

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

getContents(): ?string

Gibt den Inhalt der hochgeladenen Datei zurück. War der Upload nicht erfolgreich, gibt sie null zurück.

getContentType(): ?string

Erkennt den MIME-Content-Type der hochgeladenen Datei anhand ihrer Signatur. War der Upload nicht erfolgreich oder ist die Erkennung fehlgeschlagen, gibt sie null zurück.

Erfordert die PHP-Extension fileinfo.

getUntrustedName(): string

Gibt den ursprünglichen Dateinamen zurück, wie ihn der Browser gesendet hat.

Trauen Sie dem von dieser Methode zurückgegebenen Wert nicht. Ein Client könnte einen bösartigen Dateinamen senden, um Ihre Anwendung zu beschädigen oder zu kompromittieren.

getSanitizedName(): string

Gibt den bereinigten Dateinamen zurück. Er enthält nur die ASCII-Zeichen [a-zA-Z0-9.-]. Enthält der Name keine solchen Zeichen, gibt sie 'unknown' zurück. Ist die Datei ein JPEG-, PNG-, GIF-, WebP- oder AVIF-Bild, gibt sie außerdem die korrekte Dateiendung zurück.

Erfordert die PHP-Extension fileinfo.

getSuggestedExtension(): ?string

Gibt die passende Dateiendung (ohne Punkt) zurück, die dem erkannten MIME-Type entspricht.

Erfordert die PHP-Extension fileinfo.

getUntrustedFullPath(): string

Gibt den ursprünglichen Dateipfad zurück, wie ihn der Browser beim Upload eines Verzeichnisses gesendet hat. Der vollständige Pfad ist erst ab PHP 8.1 verfügbar. In früheren Versionen gibt diese Methode den ursprünglichen Dateinamen zurück.

Trauen Sie dem von dieser Methode zurückgegebenen Wert nicht. Ein Client könnte einen bösartigen Dateinamen senden, um Ihre Anwendung zu beschädigen oder zu kompromittieren.

getSize(): int

Gibt die Größe der hochgeladenen Datei zurück. War der Upload nicht erfolgreich, gibt sie 0 zurück.

getTemporaryFile(): string

Gibt den Pfad zum temporären Speicherort der hochgeladenen Datei zurück. War der Upload nicht erfolgreich, gibt sie '' zurück.

__toString(): string

Gibt den Pfad zum temporären Speicherort der hochgeladenen Datei zurück. Dadurch lässt sich das Objekt FileUpload direkt als String verwenden.

isImage(): bool

Gibt true zurück, wenn die hochgeladene Datei ein JPEG-, PNG-, GIF-, WebP- oder AVIF-Bild ist. Die Erkennung erfolgt anhand der Signatur und prüft nicht die Integrität der gesamten Datei. Ob ein Bild beschädigt ist, lässt sich zum Beispiel dadurch feststellen, dass man es zu laden versucht.

Erfordert die PHP-Extension fileinfo.

getImageSize(): ?array

Gibt ein Paar [Breite, Höhe] mit den Abmessungen des hochgeladenen Bildes zurück. War der Upload nicht erfolgreich oder handelt es sich nicht um ein gültiges Bild, gibt sie null zurück.

toImage(): Nette\Utils\Image

Lädt das Bild als Objekt Image. War der Upload nicht erfolgreich oder handelt es sich nicht um ein gültiges Bild, wirft sie eine Nette\Utils\ImageException.

Version: 4.x