Skip to content
opensas edited this page Apr 26, 2012 · 4 revisions

Rutas HTTP

El router (enrutador) HTTP de Play

El router es el componente encargado de traducir las solicitudes HTTP entrantes en una llamada a una acción.

Una solicitud HTTP es vista por el framework MVC como un evento. Este evento contiene dos partes importantes de información:

  • el path de la solicitud (tal como /clients/1542, /photos/list), incluyendo el querystring.
  • el método HTTP (GET, POST, …).

Las rutas se definen en el fichero conf/routes, que es compilado. Esto implica que podrá ver los errores de las rutas directamente en el navegador:

Sintaxis del archivo conf/routes

conf/routes es el fichero de configuración que utiliza el router. Este fichero lista todas las rutas que necesita la aplicación. Cada ruta consiste en un método HTTP y el patrón URI, ambos asociados con una llamada a un generador de Actions.

Veamos cómo son las definiciones de ruta:

GET   /clients/:id          controllers.Clients.show(id: Long)  

Cada ruta comienza con el método HTTP, seguido del patrón URI. El último elemento de una ruta es la definición de la llamada.

También se pueden añadir comentarios al fichero de rutas, con el carácter #:

# Muestra un cliente.
GET   /clients/:id          controllers.Clients.show(id: Long)  

El método HTTP

El método HTTP puede ser cualquiera de los métodos válidos soportados por HTTP (GET, POST, PUT, DELETE, HEAD).

El patrón URI

Define el path de solicitud de la ruta. Algunas partes del path pueden ser dinámicas.

Path estático

Por ejemplo, para coincidir exactamente con las solicitudes entrantes GET /clients/all puede definir esta ruta:

GET   /clients/all              controllers.Clients.list()

Partes dinámicas

Si quiere definir una ruta que, digamos, recupere un cliente por id, tiene que añadir una parte dinámica:

GET   /clients/:id          controllers.Clients.show(id: Long)  

Tenga en cuenta que el patrón URI puede tener más de una parte dinámica.

La estrategia por defecto para capturar una parte dinámica se define con la expresión regular [^/]+, que indica que cualquier parte dinámica definida como :id capturará exactamente un segmento del path.

Partes dinámicas que se extienden a varios /

Si quiere que una parte dinámica capture más de un segmento del path URI separados por barras /, puede definir la parte dinámica usando la sintaxis *id, que usa la expresión regular .*:

GET   /files/*name          controllers.Application.download(name)  

En este caso, para una solicitud como GET /files/images/logo.png, la parte dinámica name capturará el valor images/logo.png.

Partes dinámicas con expresiones regulares personalizadas

También puede definir su propia expresión regular para una parte dinámica, con la sintaxis $id<regex>:

GET   /clients/$id<[0-9]+>  controllers.Clients.show(id: Long)  

Llamada a un método de acción

La última parte de una definición de ruta es la llamada. Esta parte ha de definir una llamada válida a un método que retorne un valor de tipo play.api.mvc.Action, el cual típicamente será un método de acción de un controlador.

Si el método no define ningún parámetro, basta poner el nombre completo del método:

GET   /                     controllers.Application.homePage()

Si el método de acción define parámetros, los valores correspondientes a los parámetros se buscarán en la URI de solicitud, ya sea extrayéndolos del path en sí mismo, o a partir de la cadena de consulta (query string).

# Extraer el parámetro page del path.
# p.ej. http://myserver.com/index
GET   /:page                controllers.Application.show(page)

O bien:

# Extraer el parámetro page de la query string
# p.ej. http://myserver.com/?page=index
GET   /                     controllers.Application.show(page)

Esta es la correspondiente definición del método show en el controlador controllers.Application:

def show(page: String) = Action {
    loadContentFromDatabase(page).map { htmlContent =>
        Ok(htmlContent).as("text/html")
    }.getOrElse(NotFound)
}

Tipos de parámetros

Para los parámetros de tipo String el tipo de parámetro es opcional. Si quiere que Play lo transforme en un tipo específico de Scala, puedes añadir el tipo de manera explícita:

GET   /client/:id           controllers.Clients.show(id: Long)

Y luego usar el mismo tipo en el correspondiente método de acción en el controlador:

def show(id: Long) = Action {
    Client.findById(id).map { client =>
        Ok(views.html.Clients.display(client))
    }.getOrElse(NotFound)
}

Parámetros con valores fijos

A veces querrá utilizar un valor fijo para un parámetro:

# Extraer el parámetro page del path o poner valor por defecto si llega /
GET   /                     controllers.Application.show(page = "home")
GET   /:page                controllers.Application.show(page)

Parámetros con valores por defecto

También puede proporcionar un valor por defecto a ser utilizando en caso de no encontrar el valor en la solicitud entrante:

# Enlaces de paginación, como /clients?page=3
GET   /clients              controllers.Clients.list(page: Int ?= 1)

Prioridad de las rutas

Muchas rutas pueden coincidir con el mismo pedido HTTP. Si hay conflicto, se usará la primera ruta (en el orden en que están declaradas).

Rutas invertidas

El router puede usarse para generar una URL a partir de una llamada Java. Con ello se hace posible centralizar todos los patrones URI en un solo fichero de configuración, lo que le da mayor tranquilidad a la hora de reestructurar su aplicación.

Por cada controlador que se usa en el fichero de rutas, el router genera un 'controlador invertido' en el paquete routes, que tiene los mismos métodos de acción, con la misma cantidad y tipos de parámetros, pero que devuelven un play.api.mvc.Call en vez de un play.api.mvc.Action.

El play.api.mvc.Call define una llamada HTTP, y proporciona tanto el método HTTP como la URI.

Por ejemplo, si crea un controlador como:

package controllers

import play.api._
import play.api.mvc._

object Application extends Controller {
    
  def hello(name: String) = Action {
      Ok("Hello " + name + "!")
  }
    
}

Y lo asigna en el fichero conf/routes:

# Hello action
GET   /hello/:name          controllers.Application.hello(name)

Puede obtener la URL que invocaría al método de acción hello, usando el controlador invertido controllers.routes.Application:

// Redirect to /hello/Bob
def helloBob = Action {
    Redirect(routes.Application.hello("Bob"))    
}

Siguiente: Manipulando la respuesta

Clone this wiki locally