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 SubdomainFetchSite::CrossSite– von einer fremden SiteFetchSite::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.