# Enrutamiento y enmascaramiento de URL

[← Volver al índice](../crudl.md)

## Parámetros de URL conocidos por el controlador

Los parámetros de URL están disponibles en `@http_context/request/get`.

| Parámetro | Requerido | Descripción |
|---|---|---|
| `_entities_type` | Sí | Tipo de entidades sobre las que aplicarán las operaciones. Determina también la carpeta de la entidad y, salvo que se indique `@table_name`, el nombre de la tabla. |
| `_entity_id` | No | Clave primaria o identificador de la entidad. Su presencia o ausencia determina la operación. |
| `_key` | No | Nombre del campo usado como identificador. Si no se indica, se asume `sys_pk`. |
| `_app_group` | No | Nombre de un grupo de aplicaciones configurado en el administrador de conexiones. |
| `_connection` | No | Nombre de una conexión dentro del grupo de aplicaciones indicado. |
| `ws` | No | Identificador de espacio de trabajo. Su presencia activa el modo de conexión por suplantación de identidad. |

Para cualquier forma de conexión deberá indicar `_entities_type`. Los demás solo se requieren según sus configuraciones.

Existen otros parámetros que controlan el comportamiento de la redirección; ver [Patrón PRG y redirección](prg-y-redireccion.md).

## Mapeo hacia el punto de entrada

Aunque los parámetros de URL pueden establecerse como tales, resulta conveniente indicarlos a través de reglas en `routes.map`.

```
/misistema/{_entities_type}/{_entity_id?} > carpetademisistema/entry-point.dkl
```

Ejemplos:

* URL sin mapa: `https://midominio.com/misistema/entry-point.dkl?_entities_type=cliente&_entity_id=10`
* URL con mapa: `https://midominio.com/misistema/cliente/10`

La sintaxis completa de `routes.map`, incluidos los parámetros opcionales (`?`), los numéricos (`#`), las rutas absolutas (`$`) y la prioridad de reglas, se documenta en [El flujo de la solicitud HTTP](../flujo-http.md).

## Enmascaramiento de URL

Para brindar URLs más descriptivas y organizar mejor su sistema, es posible enmascarar los puntos finales y redirigirlos a entidades específicas.

Suponga un CRUD-L para comprobantes de movimientos de almacén. Las entidades podrían llamarse `moventrada` y `movsalida`, lo que significaría rutas como:

```
/misistema/moventrada
/misistema/movsalida
```

Estas otras son más descriptivas y ofrecen mejor organización:

```
/misistema/inventarios/movimientos/entrada
/misistema/inventarios/movimientos/salida
```

### Cómo funciona

El enmascaramiento se apoya en dos pasos:

1. `routes.map` descompone la URL en parámetros GET con nombres que usted elige.
2. `crudl.routes.pattern` declara **qué parámetros GET y en qué orden** forman la ruta lógica; `crudl.routes.entity` compara esa ruta lógica contra un valor esperado y, si coincide, asigna `_entities_type`.

El punto que suele causar confusión: los segmentos que se indican en `crudl.routes.pattern` **no son segmentos de la URL, son nombres de parámetros GET**. Deben coincidir con los nombres de los marcadores declarados en `routes.map`.

### Funciones

#### crudl.routes.pattern

```
do crudl.routes.pattern("/segmento1/segmento2/segmento3")
```

Declara un patrón. Cada segmento es el nombre de un parámetro GET. Al resolver, se lee el valor de cada parámetro en orden y se concatenan con `/` para formar la ruta lógica. Si un parámetro está vacío, la construcción se detiene ahí.

Las diagonales inicial y final son opcionales y se normalizan.

#### crudl.routes.entity

```
if crudl.routes.entity("inventarios/movimientos/entrada", "moventrada")
{
    // La ruta coincide y se ha asignado _entities_type
}
```

Compara la ruta lógica resuelta contra el primer argumento. Si coinciden, asigna el segundo argumento a `_entities_type` y devuelve `1`; en caso contrario devuelve `0`.

La comparación no distingue mayúsculas y minúsculas, y las diagonales inicial y final se normalizan.

#### crudl.route

```
if crudl.route("inventarios/movimientos/entrada")
{
    // La ruta coincide, pero no se modifica _entities_type
}
```

Equivale a `crudl.routes.entity` con una entidad vacía. Útil para ejecutar lógica condicional según la ruta sin cambiar la entidad.

### Ejemplo completo

**`_protected/routes.map`**

```
/misistema/{modulo}/{submodulo}/{proceso}/{_entity_id?} > misistema/entry-point.dkl
```

**`entry-point.dkl`**

```
do crudl.routes.pattern("/modulo/submodulo/proceso")

do crudl.routes.entity("inventarios/movimientos/entrada", "moventrada")
do crudl.routes.entity("inventarios/movimientos/salida",  "movsalida")
```

Con esta configuración, la solicitud:

```
GET /misistema/inventarios/movimientos/entrada/15
```

produce los parámetros GET `modulo=inventarios`, `submodulo=movimientos`, `proceso=entrada` y `_entity_id=15`. El patrón los recompone como `inventarios/movimientos/entrada`, coincide con la primera regla y asigna `_entities_type=moventrada`.

Observe que el patrón tiene tres segmentos porque son tres los parámetros que forman la ruta lógica; `misistema` es parte de la URL pero no un parámetro, y `_entity_id` no forma parte de la ruta lógica.

### Un patrón por punto de entrada

Registre un solo patrón por punto de entrada. Si necesita atender estructuras de URL distintas, use puntos de entrada distintos.

## Definición declarativa con routes.json

En lugar de escribir las llamadas en el punto de entrada, puede declarar los patrones y las rutas en un archivo JSON.

La función `crudl.loadRoutesJSON()` busca el archivo indicado por `@crudl_routes_json` (predeterminado `routes.json`) en la ruta `@path_root` + `@base_path`, y ejecuta por usted las llamadas a `crudl.routes.pattern` y `crudl.routes.entity`.

**Estructura del archivo**

```json
[
  {
    "pattern": "/modulo/submodulo/proceso",
    "routes": [
      { "route": "inventarios/movimientos/entrada", "entity_type": "moventrada" },
      { "route": "inventarios/movimientos/salida",  "entity_type": "movsalida"  }
    ]
  }
]
```

Los elementos cuyo `pattern`, `route` o `entity_type` estén vacíos se omiten. Si el archivo no existe, la función no hace nada.

Para cambiar el nombre del archivo, establezca `@crudl_routes_json` antes de la llamada:

```
@crudl_routes_json = "rutas-inventarios.json"
do crudl.loadRoutesJSON()
```

## Documentos relacionados

* [El controlador](controlador.md)
* [Archivo de configuración `.crudl`](configuracion.md)
* [El flujo de la solicitud HTTP](../flujo-http.md)
