Nette Documentation Preview

syntax
Petición HTTP
*************

.[perex]
Nette encapsula la petición HTTP en objetos con una API clara y ofrece a la vez un filtro de saneamiento.

La petición HTTP está representada por el objeto [api:Nette\Http\Request]. Si trabaja con Nette, el framework crea este objeto automáticamente y puede hacer que se lo pasen mediante [inyección de dependencias |dependency-injection:passing-dependencies]. En los presenters basta con llamar al método `$this->getHttpRequest()`. Si trabaja fuera de Nette Framework, puede crear el objeto con [#RequestFactory].

Una gran ventaja de Nette es que, al crear el objeto, sanea automáticamente todos los parámetros de entrada (GET, POST, COOKIE) y también la URL, eliminando los caracteres de control y las secuencias UTF-8 no válidas. Después puede trabajar con esos datos con seguridad. Los datos saneados se usan a continuación en los presenters y los formularios.

→ [Instalación y requisitos |@home#Instalación]


Nette\Http\Request
==================

Este objeto es inmutable. No tiene setters; tiene solo un llamado wither, `withUrl()`, que no cambia el objeto sino que devuelve una nueva instancia con el valor modificado.


withUrl(Nette\Http\UrlScript $url): Nette\Http\Request .[method]
----------------------------------------------------------------
Devuelve un clon con otra URL.


getUrl(): Nette\Http\UrlScript .[method]
----------------------------------------
Devuelve la URL de la petición como objeto [UrlScript |urls#UrlScript].

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

Atención: los navegadores no envían el fragmento al servidor, así que `$url->getFragment()` devolverá una cadena vacía.


getQuery(?string $key=null): string|array|null .[method]
--------------------------------------------------------
Devuelve los parámetros GET de la petición.

```php
$all = $httpRequest->getQuery();    // array de todos los parámetros de la URL
$id = $httpRequest->getQuery('id'); // devuelve el parámetro GET 'id' (o null)
```


getPost(?string $key=null): string|array|null .[method]
-------------------------------------------------------
Devuelve los parámetros POST de la petición.

```php
$all = $httpRequest->getPost();     // array de todos los parámetros POST
$id = $httpRequest->getPost('id');  // devuelve el parámetro POST 'id' (o null)
```


getFile(string|string[] $key): ?Nette\Http\FileUpload .[method]
---------------------------------------------------------------
Devuelve un [archivo subido |#Archivos subidos] como objeto [api:Nette\Http\FileUpload]:

```php
$file = $httpRequest->getFile('avatar');
if ($file?->hasFile()) { // ¿se subió algún archivo?
	$file->getUntrustedName(); // nombre de archivo enviado por el usuario
	$file->getSanitizedName(); // nombre sin caracteres peligrosos
}
```

Para acceder a una estructura anidada, indique un array de claves.

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

Como no puede fiarse de los datos externos y por tanto tampoco de la estructura de los archivos, este enfoque es más seguro que, por ejemplo, `$request->getFiles()['my-form']['details']['avatar']`, que podría fallar.


getFiles(): array .[method]
---------------------------
Devuelve un árbol de [todos los archivos subidos |#Archivos subidos] en una estructura normalizada cuyas hojas son objetos [api:Nette\Http\FileUpload]:

```php
$files = $httpRequest->getFiles();
```


getCookie(string $key): ?string .[method]
-----------------------------------------
Devuelve una cookie, o `null` si no existe.

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


getCookies(): array .[method]
-----------------------------
Devuelve todas las cookies.

```php
$cookies = $httpRequest->getCookies();
```


getMethod(): string .[method]
-----------------------------
Devuelve el método HTTP usado en la petición.

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


isMethod(string $method): bool .[method]
----------------------------------------
Comprueba el método HTTP usado en la petición. El parámetro no distingue mayúsculas de minúsculas.

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


getHeader(string $header): ?string .[method]
--------------------------------------------
Devuelve una cabecera HTTP, o `null` si no existe. El parámetro no distingue mayúsculas de minúsculas.

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


getHeaders(): array<string, string> .[method]
---------------------------------------------
Devuelve todas las cabeceras HTTP como array asociativo. Las claves están normalizadas a minúsculas.

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


isSecured(): bool .[method]
---------------------------
¿Está cifrada la conexión (HTTPS)? Para que funcione correctamente puede hacer falta [configurar un proxy |configuration#Proxy HTTP].


isSameSite(): bool .[method deprecated]
---------------------------------------
¿Llegó la petición desde el mismo sitio? Desde la versión 3.4 lo sustituye el más capaz [isFrom() |#isFrom()].


isFrom(FetchSite|array $site, FetchDest|array|null $dest=null, ?bool $user=null): bool .[method]{data-version:3.4.0}
--------------------------------------------------------------------------------------------------------------------
Le dice de dónde llegó la petición y cómo la hizo el navegador, a partir de las cabeceras `Sec-Fetch-*` (los llamados [Fetch Metadata |https://developer.mozilla.org/en-US/docs/Glossary/Fetch_metadata_request_header]), que el navegador pone él mismo y que una página que se ejecute en el navegador de la víctima no puede falsificar ni eliminar. Nette las usa internamente para proteger automáticamente los formularios y las señales contra el [Cross-Site Request Forgery |nette:glossary#Cross-Site Request Forgery (CSRF)] (CSRF). Es útil cuando quiera proteger sus propias acciones sensibles, como endpoints de API o enlaces destructivos.

El método devuelve `true` solo cuando la petición cumple **todas** las condiciones que indique. El primer parámetro `$site` describe la relación entre la página que inició la petición y su sitio (la cabecera `Sec-Fetch-Site`). Acepta un único valor o una lista de estos casos de `FetchSite`:

- `FetchSite::SameOrigin`: del mismo origen exacto (esquema, host y puerto)
- `FetchSite::SameSite`: del mismo sitio, posiblemente de otro subdominio
- `FetchSite::CrossSite`: de un sitio ajeno
- `FetchSite::None`: la inició directamente el usuario, p. ej. escribiendo la URL o abriendo un marcador

```php
// ¿procede la petición de nuestras propias páginas?
if (!$httpRequest->isFrom([FetchSite::SameOrigin, FetchSite::SameSite])) {
	// bloquea la acción
}
```

El parámetro opcional `$dest` (la cabecera `Sec-Fetch-Dest`) dice qué tipo de recurso está obteniendo el navegador, p. ej. `FetchDest::Document` para una navegación de nivel superior o `FetchDest::Empty` para una petición hecha desde JavaScript. El parámetro opcional `$user` (la cabecera `Sec-Fetch-User`) indica si la navegación la desencadenó una acción real del usuario, como pulsar un enlace o enviar un formulario; pase `true` para exigirlo.

Una comprobación de que una acción solo es accesible desde sus propias páginas y solo mediante una acción real del usuario tiene entonces este aspecto:

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

.[note]
Los navegadores antiguos (Safari anterior a 16.4) no envían las cabeceras `Sec-Fetch-*`. Para ellos, Nette recurre a una cookie `SameSite=Strict` que solo demuestra que la petición no es cross-site. Una comprobación que exija además `$dest` o `$user` no se puede verificar así y devuelve `false` en esos navegadores; si eso es demasiado estricto, compruebe solo `$site`.


isAjax(): bool .[method]
------------------------
¿Es una petición AJAX?


getRemoteAddress(): ?string .[method]
-------------------------------------
Devuelve la dirección IP del usuario. Para que funcione correctamente puede hacer falta [configurar un proxy |configuration#Proxy HTTP].


getRemoteHost(): ?string .[method deprecated]
---------------------------------------------
Obsoleto, devuelve siempre `null`. Las consultas DNS inversas eran lentas y poco fiables; si necesita el nombre del host, resuélvalo usted mismo a partir de [getRemoteAddress() |#getRemoteAddress()].


getBasicCredentials(): ?array .[method]
---------------------------------------
Devuelve las credenciales de autenticación de la [autenticación HTTP Basic |https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication].

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


getRawBody(): ?string .[method]
-------------------------------
Devuelve el cuerpo de la petición HTTP.

```php
$body = $httpRequest->getRawBody();
```


getOrigin(): ?UrlImmutable .[method]
------------------------------------
Devuelve el origen desde el que llegó la petición. Un origen se compone del esquema (protocolo), el nombre de host y el puerto, por ejemplo `https://example.com:8080`. Devuelve `null` si la cabecera de origen no está presente o vale `'null'`.

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

El navegador envía la cabecera `Origin` en los siguientes casos:
- peticiones cross-origin (llamadas AJAX a otro dominio)
- peticiones POST, PUT, DELETE y otras que modifican
- peticiones hechas con la Fetch API

El navegador NO envía la cabecera `Origin` en:
- las peticiones GET corrientes al mismo dominio (navegación same-origin)
- la navegación directa escribiendo una URL en la barra de direcciones
- las peticiones de clientes que no son navegadores

.[note]
A diferencia de la cabecera `Referer`, `Origin` contiene solo el esquema, el host y el puerto, no la ruta completa de la URL. Eso la hace más adecuada para las comprobaciones de seguridad y preserva la privacidad del usuario. La cabecera `Origin` se usa sobre todo para la validación [CORS |nette:glossary#Cross-Origin Resource Sharing (CORS)] (Cross-Origin Resource Sharing).


detectLanguage(array $langs): ?string .[method]
-----------------------------------------------
Detecta el idioma. Pase como parámetro `$langs` un array de los idiomas que soporta la aplicación y devolverá el preferido por el navegador del visitante. No es magia; simplemente usa la cabecera `Accept-Language`. Si no encuentra ninguna coincidencia, devuelve `null`.

```php
// El navegador envía p. ej.: Accept-Language: cs,en-us;q=0.8,en;q=0.5,sl;q=0.3

$langs = ['hu', 'pl', 'en']; // idiomas soportados por la aplicación
echo $httpRequest->detectLanguage($langs); // en
```


RequestFactory
==============

La clase [api:Nette\Http\RequestFactory] sirve para crear una instancia de `Nette\Http\Request`, que representa la petición HTTP actual. (Si trabaja con Nette, el framework crea automáticamente el objeto de la petición HTTP.)

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

El método `fromGlobals()` crea el objeto de la petición a partir de las variables globales actuales de PHP (`$_GET`, `$_POST`, `$_COOKIE`, `$_FILES` y `$_SERVER`). Al crear el objeto limpia automáticamente todos los parámetros de entrada (GET, POST, COOKIE) y también la URL de caracteres de control y secuencias UTF-8 no válidas, lo que garantiza la seguridad al trabajar después con esos datos.

RequestFactory se puede configurar antes de llamar a `fromGlobals()`:

- el método `$factory->setBinary()` desactiva la limpieza automática de los parámetros de entrada de caracteres de control y secuencias UTF-8 no válidas.
- el método `$factory->setProxy(...)` indica la dirección IP del [servidor proxy |configuration#Proxy HTTP], necesaria para detectar correctamente la dirección IP del usuario.
- el método `$factory->setForceHttps()` .{data-version:3.3.4} fuerza el esquema HTTPS de la petición independientemente del entorno del servidor.

RequestFactory permite definir filtros que transforman automáticamente partes de la URL de la petición. Estos filtros eliminan de las URL caracteres no deseados que pueden haber insertado, por ejemplo, implementaciones incorrectas de los sistemas de comentarios de distintos sitios web:

```php
// elimina los espacios de la ruta
$requestFactory->urlFilters['path']['%20'] = '';

// elimina el punto, la coma o el paréntesis derecho del final del URI
$requestFactory->urlFilters['url']['[.,)]$'] = '';

// limpia la ruta de barras dobles (filtro predeterminado)
$requestFactory->urlFilters['path']['/{2,}'] = '/';
```

La primera clave, `'path'` o `'url'`, determina a qué parte de la URL se aplicará el filtro. La segunda clave es la expresión regular que se busca y el valor es el reemplazo que se usará en lugar del texto encontrado.


Archivos subidos
================

El método `Nette\Http\Request::getFiles()` devuelve un array de todos los archivos subidos en una estructura normalizada cuyas hojas son objetos [api:Nette\Http\FileUpload]. Estos encapsulan los datos enviados por el elemento de formulario `<input type=file>`.

La estructura refleja los nombres de los elementos en HTML. En el caso más simple puede tratarse de un único elemento de formulario con nombre, enviado como:

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

En ese caso, `$request->getFiles()` devuelve el array:

```php
[
	'avatar' => /* instancia de FileUpload */
]
```

El objeto `FileUpload` se crea aunque el usuario no haya subido ningún archivo o la subida haya fallado. El método `hasFile()` devuelve true si se envió un archivo:

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

En el caso de un nombre de elemento con notación de array:

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

el árbol devuelto tiene este aspecto:

```php
[
	'my-form' => [
		'details' => [
			'avatar' => /* instancia de FileUpload */
		],
	],
]
```

También puede crear arrays de archivos:

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

En ese caso, la estructura tiene este aspecto:

```php
[
	'my-form' => [
		'details' => [
			'avatars' => [
				0 => /* instancia de FileUpload */,
				1 => /* instancia de FileUpload */,
				2 => /* instancia de FileUpload */,
			],
		],
	],
]
```

La mejor forma de acceder al índice 1 del array anidado es esta:

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

Como no puede fiarse de los datos externos y por tanto tampoco de la estructura de los archivos, este enfoque es más seguro que, por ejemplo, `$request->getFiles()['my-form']['details']['avatars'][1]`, que podría fallar.


Resumen de los métodos de `FileUpload` .{toc: FileUpload}
---------------------------------------------------------


hasFile(): bool .[method]
-------------------------
Devuelve `true` si el usuario subió un archivo.


isOk(): bool .[method]
----------------------
Devuelve `true` si el archivo se subió correctamente.


getError(): int .[method]
-------------------------
Devuelve el código de error asociado al archivo subido. Es una de las constantes [UPLOAD_ERR_XXX |https://php.net/manual/en/features.file-upload.errors.php]. Si el archivo se subió correctamente, devuelve `UPLOAD_ERR_OK`.


move(string $dest) .[method]
----------------------------
Mueve un archivo subido a una nueva ubicación. Si el archivo de destino ya existe, se sobrescribirá.

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


getContents(): ?string .[method]
--------------------------------
Devuelve el contenido del archivo subido. Si la subida no fue correcta, devuelve `null`.


getContentType(): ?string .[method]
-----------------------------------
Detecta el tipo de contenido MIME del archivo subido a partir de su firma. Si la subida no fue correcta o la detección falló, devuelve `null`.

.[caution]
Requiere la extensión de PHP `fileinfo`.


getUntrustedName(): string .[method]
------------------------------------
Devuelve el nombre original del archivo tal y como lo envió el navegador.

.[caution]
No se fíe del valor que devuelve este método. Un cliente podría enviar un nombre de archivo malicioso con la intención de dañar o comprometer su aplicación.


getSanitizedName(): string .[method]
------------------------------------
Devuelve el nombre de archivo saneado. Contiene solo caracteres ASCII `[a-zA-Z0-9.-]`. Si el nombre no contiene esos caracteres, devuelve `'unknown'`. Si el archivo es una imagen JPEG, PNG, GIF, WebP o AVIF, devuelve además la extensión de archivo correcta.

.[caution]
Requiere la extensión de PHP `fileinfo`.


getSuggestedExtension(): ?string .[method]{data-version:3.2.4}
--------------------------------------------------------------
Devuelve la extensión de archivo adecuada (sin el punto) que corresponde al tipo MIME detectado.

.[caution]
Requiere la extensión de PHP `fileinfo`.


getUntrustedFullPath(): string .[method]
----------------------------------------
Devuelve la ruta original del archivo tal y como la envió el navegador al subir un directorio. La ruta completa solo está disponible en PHP 8.1 y superior. En versiones anteriores, este método devuelve el nombre original del archivo.

.[caution]
No se fíe del valor que devuelve este método. Un cliente podría enviar un nombre de archivo malicioso con la intención de dañar o comprometer su aplicación.


getSize(): int .[method]
------------------------
Devuelve el tamaño del archivo subido. Si la subida no fue correcta, devuelve `0`.


getTemporaryFile(): string .[method]
------------------------------------
Devuelve la ruta a la ubicación temporal del archivo subido. Si la subida no fue correcta, devuelve `''`.


__toString(): string .[method]
------------------------------
Devuelve la ruta a la ubicación temporal del archivo subido. Eso permite usar el objeto `FileUpload` directamente como cadena.


isImage(): bool .[method]
-------------------------
Devuelve `true` si el archivo subido es una imagen JPEG, PNG, GIF, WebP o AVIF. La detección se basa en su firma y no verifica la integridad del archivo entero. Si una imagen está dañada se puede averiguar, por ejemplo, intentando [cargarla |#toImage()].

.[caution]
Requiere la extensión de PHP `fileinfo`.


getImageSize(): ?array .[method]
--------------------------------
Devuelve el par `[width, height]` con las dimensiones de la imagen subida. Si la subida no fue correcta o no es una imagen válida, devuelve `null`.


toImage(): Nette\Utils\Image .[method]
--------------------------------------
Carga la imagen como objeto [Image |utils:images]. Si la subida no fue correcta o no es una imagen válida, lanza una `Nette\Utils\ImageException`.

Petición HTTP

Nette encapsula la petición HTTP en objetos con una API clara y ofrece a la vez un filtro de saneamiento.

La petición HTTP está representada por el objeto Nette\Http\Request. Si trabaja con Nette, el framework crea este objeto automáticamente y puede hacer que se lo pasen mediante inyección de dependencias. En los presenters basta con llamar al método $this->getHttpRequest(). Si trabaja fuera de Nette Framework, puede crear el objeto con RequestFactory.

Una gran ventaja de Nette es que, al crear el objeto, sanea automáticamente todos los parámetros de entrada (GET, POST, COOKIE) y también la URL, eliminando los caracteres de control y las secuencias UTF-8 no válidas. Después puede trabajar con esos datos con seguridad. Los datos saneados se usan a continuación en los presenters y los formularios.

Instalación y requisitos

Nette\Http\Request

Este objeto es inmutable. No tiene setters; tiene solo un llamado wither, withUrl(), que no cambia el objeto sino que devuelve una nueva instancia con el valor modificado.

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

Devuelve un clon con otra URL.

getUrl(): Nette\Http\UrlScript

Devuelve la URL de la petición como objeto UrlScript.

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

Atención: los navegadores no envían el fragmento al servidor, así que $url->getFragment() devolverá una cadena vacía.

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

Devuelve los parámetros GET de la petición.

$all = $httpRequest->getQuery();    // array de todos los parámetros de la URL
$id = $httpRequest->getQuery('id'); // devuelve el parámetro GET 'id' (o null)

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

Devuelve los parámetros POST de la petición.

$all = $httpRequest->getPost();     // array de todos los parámetros POST
$id = $httpRequest->getPost('id');  // devuelve el parámetro POST 'id' (o null)

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

Devuelve un archivo subido como objeto Nette\Http\FileUpload:

$file = $httpRequest->getFile('avatar');
if ($file?->hasFile()) { // ¿se subió algún archivo?
	$file->getUntrustedName(); // nombre de archivo enviado por el usuario
	$file->getSanitizedName(); // nombre sin caracteres peligrosos
}

Para acceder a una estructura anidada, indique un array de claves.

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

Como no puede fiarse de los datos externos y por tanto tampoco de la estructura de los archivos, este enfoque es más seguro que, por ejemplo, $request->getFiles()['my-form']['details']['avatar'], que podría fallar.

getFiles(): array

Devuelve un árbol de todos los archivos subidos en una estructura normalizada cuyas hojas son objetos Nette\Http\FileUpload:

$files = $httpRequest->getFiles();

getCookie(string $key): ?string

Devuelve una cookie, o null si no existe.

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

getCookies(): array

Devuelve todas las cookies.

$cookies = $httpRequest->getCookies();

getMethod(): string

Devuelve el método HTTP usado en la petición.

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

isMethod(string $method)bool

Comprueba el método HTTP usado en la petición. El parámetro no distingue mayúsculas de minúsculas.

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

getHeader(string $header): ?string

Devuelve una cabecera HTTP, o null si no existe. El parámetro no distingue mayúsculas de minúsculas.

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

getHeaders(): array<string, string>

Devuelve todas las cabeceras HTTP como array asociativo. Las claves están normalizadas a minúsculas.

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

isSecured(): bool

¿Está cifrada la conexión (HTTPS)? Para que funcione correctamente puede hacer falta configurar un proxy.

isSameSite(): bool

¿Llegó la petición desde el mismo sitio? Desde la versión 3.4 lo sustituye el más capaz isFrom().

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

Le dice de dónde llegó la petición y cómo la hizo el navegador, a partir de las cabeceras Sec-Fetch-* (los llamados Fetch Metadata), que el navegador pone él mismo y que una página que se ejecute en el navegador de la víctima no puede falsificar ni eliminar. Nette las usa internamente para proteger automáticamente los formularios y las señales contra el Cross-Site Request Forgery (CSRF). Es útil cuando quiera proteger sus propias acciones sensibles, como endpoints de API o enlaces destructivos.

El método devuelve true solo cuando la petición cumple todas las condiciones que indique. El primer parámetro $site describe la relación entre la página que inició la petición y su sitio (la cabecera Sec-Fetch-Site). Acepta un único valor o una lista de estos casos de FetchSite:

  • FetchSite::SameOrigin: del mismo origen exacto (esquema, host y puerto)
  • FetchSite::SameSite: del mismo sitio, posiblemente de otro subdominio
  • FetchSite::CrossSite: de un sitio ajeno
  • FetchSite::None: la inició directamente el usuario, p. ej. escribiendo la URL o abriendo un marcador
// ¿procede la petición de nuestras propias páginas?
if (!$httpRequest->isFrom([FetchSite::SameOrigin, FetchSite::SameSite])) {
	// bloquea la acción
}

El parámetro opcional $dest (la cabecera Sec-Fetch-Dest) dice qué tipo de recurso está obteniendo el navegador, p. ej. FetchDest::Document para una navegación de nivel superior o FetchDest::Empty para una petición hecha desde JavaScript. El parámetro opcional $user (la cabecera Sec-Fetch-User) indica si la navegación la desencadenó una acción real del usuario, como pulsar un enlace o enviar un formulario; pase true para exigirlo.

Una comprobación de que una acción solo es accesible desde sus propias páginas y solo mediante una acción real del usuario tiene entonces este aspecto:

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

Los navegadores antiguos (Safari anterior a 16.4) no envían las cabeceras Sec-Fetch-*. Para ellos, Nette recurre a una cookie SameSite=Strict que solo demuestra que la petición no es cross-site. Una comprobación que exija además $dest o $user no se puede verificar así y devuelve false en esos navegadores; si eso es demasiado estricto, compruebe solo $site.

isAjax(): bool

¿Es una petición AJAX?

getRemoteAddress(): ?string

Devuelve la dirección IP del usuario. Para que funcione correctamente puede hacer falta configurar un proxy.

getRemoteHost(): ?string

Obsoleto, devuelve siempre null. Las consultas DNS inversas eran lentas y poco fiables; si necesita el nombre del host, resuélvalo usted mismo a partir de getRemoteAddress().

getBasicCredentials(): ?array

Devuelve las credenciales de autenticación de la autenticación HTTP Basic.

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

getRawBody(): ?string

Devuelve el cuerpo de la petición HTTP.

$body = $httpRequest->getRawBody();

getOrigin(): ?UrlImmutable

Devuelve el origen desde el que llegó la petición. Un origen se compone del esquema (protocolo), el nombre de host y el puerto, por ejemplo https://example.com:8080. Devuelve null si la cabecera de origen no está presente o vale 'null'.

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

El navegador envía la cabecera Origin en los siguientes casos:

  • peticiones cross-origin (llamadas AJAX a otro dominio)
  • peticiones POST, PUT, DELETE y otras que modifican
  • peticiones hechas con la Fetch API

El navegador NO envía la cabecera Origin en:

  • las peticiones GET corrientes al mismo dominio (navegación same-origin)
  • la navegación directa escribiendo una URL en la barra de direcciones
  • las peticiones de clientes que no son navegadores

A diferencia de la cabecera Referer, Origin contiene solo el esquema, el host y el puerto, no la ruta completa de la URL. Eso la hace más adecuada para las comprobaciones de seguridad y preserva la privacidad del usuario. La cabecera Origin se usa sobre todo para la validación CORS (Cross-Origin Resource Sharing).

detectLanguage(array $langs): ?string

Detecta el idioma. Pase como parámetro $langs un array de los idiomas que soporta la aplicación y devolverá el preferido por el navegador del visitante. No es magia; simplemente usa la cabecera Accept-Language. Si no encuentra ninguna coincidencia, devuelve null.

// El navegador envía p. ej.: Accept-Language: cs,en-us;q=0.8,en;q=0.5,sl;q=0.3

$langs = ['hu', 'pl', 'en']; // idiomas soportados por la aplicación
echo $httpRequest->detectLanguage($langs); // en

RequestFactory

La clase Nette\Http\RequestFactory sirve para crear una instancia de Nette\Http\Request, que representa la petición HTTP actual. (Si trabaja con Nette, el framework crea automáticamente el objeto de la petición HTTP.)

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

El método fromGlobals() crea el objeto de la petición a partir de las variables globales actuales de PHP ($_GET, $_POST, $_COOKIE, $_FILES y $_SERVER). Al crear el objeto limpia automáticamente todos los parámetros de entrada (GET, POST, COOKIE) y también la URL de caracteres de control y secuencias UTF-8 no válidas, lo que garantiza la seguridad al trabajar después con esos datos.

RequestFactory se puede configurar antes de llamar a fromGlobals():

  • el método $factory->setBinary() desactiva la limpieza automática de los parámetros de entrada de caracteres de control y secuencias UTF-8 no válidas.
  • el método $factory->setProxy(...) indica la dirección IP del servidor proxy, necesaria para detectar correctamente la dirección IP del usuario.
  • el método $factory->setForceHttps() .{data-version:3.3.4} fuerza el esquema HTTPS de la petición independientemente del entorno del servidor.

RequestFactory permite definir filtros que transforman automáticamente partes de la URL de la petición. Estos filtros eliminan de las URL caracteres no deseados que pueden haber insertado, por ejemplo, implementaciones incorrectas de los sistemas de comentarios de distintos sitios web:

// elimina los espacios de la ruta
$requestFactory->urlFilters['path']['%20'] = '';

// elimina el punto, la coma o el paréntesis derecho del final del URI
$requestFactory->urlFilters['url']['[.,)]$'] = '';

// limpia la ruta de barras dobles (filtro predeterminado)
$requestFactory->urlFilters['path']['/{2,}'] = '/';

La primera clave, 'path' o 'url', determina a qué parte de la URL se aplicará el filtro. La segunda clave es la expresión regular que se busca y el valor es el reemplazo que se usará en lugar del texto encontrado.

Archivos subidos

El método Nette\Http\Request::getFiles() devuelve un array de todos los archivos subidos en una estructura normalizada cuyas hojas son objetos Nette\Http\FileUpload. Estos encapsulan los datos enviados por el elemento de formulario <input type=file>.

La estructura refleja los nombres de los elementos en HTML. En el caso más simple puede tratarse de un único elemento de formulario con nombre, enviado como:

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

En ese caso, $request->getFiles() devuelve el array:

[
	'avatar' => /* instancia de FileUpload */
]

El objeto FileUpload se crea aunque el usuario no haya subido ningún archivo o la subida haya fallado. El método hasFile() devuelve true si se envió un archivo:

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

En el caso de un nombre de elemento con notación de array:

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

el árbol devuelto tiene este aspecto:

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

También puede crear arrays de archivos:

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

En ese caso, la estructura tiene este aspecto:

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

La mejor forma de acceder al índice 1 del array anidado es esta:

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

Como no puede fiarse de los datos externos y por tanto tampoco de la estructura de los archivos, este enfoque es más seguro que, por ejemplo, $request->getFiles()['my-form']['details']['avatars'][1], que podría fallar.

Resumen de los métodos de FileUpload

hasFile(): bool

Devuelve true si el usuario subió un archivo.

isOk(): bool

Devuelve true si el archivo se subió correctamente.

getError(): int

Devuelve el código de error asociado al archivo subido. Es una de las constantes UPLOAD_ERR_XXX. Si el archivo se subió correctamente, devuelve UPLOAD_ERR_OK.

move(string $dest)

Mueve un archivo subido a una nueva ubicación. Si el archivo de destino ya existe, se sobrescribirá.

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

getContents(): ?string

Devuelve el contenido del archivo subido. Si la subida no fue correcta, devuelve null.

getContentType(): ?string

Detecta el tipo de contenido MIME del archivo subido a partir de su firma. Si la subida no fue correcta o la detección falló, devuelve null.

Requiere la extensión de PHP fileinfo.

getUntrustedName(): string

Devuelve el nombre original del archivo tal y como lo envió el navegador.

No se fíe del valor que devuelve este método. Un cliente podría enviar un nombre de archivo malicioso con la intención de dañar o comprometer su aplicación.

getSanitizedName(): string

Devuelve el nombre de archivo saneado. Contiene solo caracteres ASCII [a-zA-Z0-9.-]. Si el nombre no contiene esos caracteres, devuelve 'unknown'. Si el archivo es una imagen JPEG, PNG, GIF, WebP o AVIF, devuelve además la extensión de archivo correcta.

Requiere la extensión de PHP fileinfo.

getSuggestedExtension(): ?string

Devuelve la extensión de archivo adecuada (sin el punto) que corresponde al tipo MIME detectado.

Requiere la extensión de PHP fileinfo.

getUntrustedFullPath(): string

Devuelve la ruta original del archivo tal y como la envió el navegador al subir un directorio. La ruta completa solo está disponible en PHP 8.1 y superior. En versiones anteriores, este método devuelve el nombre original del archivo.

No se fíe del valor que devuelve este método. Un cliente podría enviar un nombre de archivo malicioso con la intención de dañar o comprometer su aplicación.

getSize(): int

Devuelve el tamaño del archivo subido. Si la subida no fue correcta, devuelve 0.

getTemporaryFile(): string

Devuelve la ruta a la ubicación temporal del archivo subido. Si la subida no fue correcta, devuelve ''.

__toString(): string

Devuelve la ruta a la ubicación temporal del archivo subido. Eso permite usar el objeto FileUpload directamente como cadena.

isImage(): bool

Devuelve true si el archivo subido es una imagen JPEG, PNG, GIF, WebP o AVIF. La detección se basa en su firma y no verifica la integridad del archivo entero. Si una imagen está dañada se puede averiguar, por ejemplo, intentando cargarla.

Requiere la extensión de PHP fileinfo.

getImageSize(): ?array

Devuelve el par [width, height] con las dimensiones de la imagen subida. Si la subida no fue correcta o no es una imagen válida, devuelve null.

toImage(): Nette\Utils\Image

Carga la imagen como objeto Image. Si la subida no fue correcta o no es una imagen válida, lanza una Nette\Utils\ImageException.