NO LEAS ESTE ARCHIVO EN GITHUB, LAS GUÍAS ESTÁN PUBLICADAS EN https://guides.rubyonrails.org.

Rails sobre Rack

Esta guía cubre la integración de Rails con Rack y la interacción con otros componentes de Rack.

Después de leer esta guía, sabrás:


ADVERTENCIA: Esta guía asume un conocimiento práctico del protocolo Rack y conceptos de Rack como middlewares, mapas de URL y Rack::Builder.

1 Introducción a Rack

Rack proporciona una interfaz mínima, modular y adaptable para desarrollar aplicaciones web en Ruby. Al envolver solicitudes y respuestas HTTP de la manera más simple posible, unifica y destila la API para servidores web, frameworks web y software intermedio (el llamado middleware) en una única llamada de método.

Explicar cómo funciona Rack no está realmente en el alcance de esta guía. En caso de que no estés familiarizado con los conceptos básicos de Rack, deberías consultar la sección de Recursos a continuación.

2 Rails sobre Rack

2.1 Objeto Rack de la Aplicación Rails

Rails.application es el objeto principal de la aplicación Rack de una aplicación Rails. Cualquier servidor web compatible con Rack debería usar el objeto Rails.application para servir una aplicación Rails.

2.2 bin/rails server

bin/rails server realiza la tarea básica de crear un objeto Rack::Server y comenzar el servidor web.

Así es como bin/rails server crea una instancia de Rack::Server:

Rails::Server.new.tap do |server|
  require APP_PATH
  Dir.chdir(Rails.application.root)
  server.start
end

El Rails::Server hereda de Rack::Server y llama al método Rack::Server#start de esta manera:

class Server < ::Rack::Server
  def start
    # ...
    super
  end
end

2.3 rackup

Para usar rackup en lugar de bin/rails server de Rails, puedes poner lo siguiente dentro de config.ru en el directorio raíz de tu aplicación Rails:

# Rails.root/config.ru
require_relative "config/environment"
run Rails.application

Y comenzar el servidor:

$ rackup config.ru

Para obtener más información sobre las diferentes opciones de rackup, puedes ejecutar:

$ rackup --help

2.4 Desarrollo y Recarga Automática

Los middlewares se cargan una vez y no se monitorean para cambios. Tendrás que reiniciar el servidor para que los cambios se reflejen en la aplicación en ejecución.

3 Pila de Middleware de Action Dispatcher

Muchos de los componentes internos de Action Dispatcher se implementan como middlewares de Rack. Rails::Application usa ActionDispatch::MiddlewareStack para combinar varios middlewares internos y externos para formar una aplicación Rack completa de Rails.

NOTA: ActionDispatch::MiddlewareStack es el equivalente de Rails a Rack::Builder, pero está construido para ofrecer mejor flexibilidad y más características para satisfacer los requisitos de Rails.

3.1 Inspeccionando la Pila de Middleware

Rails tiene un comando útil para inspeccionar la pila de middleware en uso:

$ bin/rails middleware

Para una aplicación Rails recién generada, esto podría producir algo como:

use ActionDispatch::HostAuthorization
use Rack::Sendfile
use ActionDispatch::Static
use ActionDispatch::Executor
use ActionDispatch::ServerTiming
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use ActionDispatch::RemoteIp
use Sprockets::Rails::QuietAssets
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use WebConsole::Middleware
use ActionDispatch::DebugExceptions
use ActionDispatch::ActionableExceptions
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ContentSecurityPolicy::Middleware
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
use Rack::TempfileReaper
run MyApp::Application.routes

Los middlewares predeterminados que se muestran aquí (y algunos otros) se resumen en la sección de Middlewares Internos a continuación.

3.2 Configurando la Pila de Middleware

Rails proporciona una interfaz de configuración simple config.middleware para agregar, eliminar y modificar los middlewares en la pila de middleware a través de application.rb o el archivo de configuración específico del entorno environments/<environment>.rb.

3.2.1 Agregando un Middleware

Puedes agregar un nuevo middleware a la pila de middleware usando cualquiera de los siguientes métodos:

  • config.middleware.use(new_middleware, args) - Agrega el nuevo middleware al final de la pila de middleware.

  • config.middleware.insert_before(existing_middleware, new_middleware, args) - Agrega el nuevo middleware antes del middleware existente especificado en la pila de middleware.

  • config.middleware.insert_after(existing_middleware, new_middleware, args) - Agrega el nuevo middleware después del middleware existente especificado en la pila de middleware.

# config/application.rb

# Agrega Rack::BounceFavicon al final
config.middleware.use Rack::BounceFavicon

# Agrega Lifo::Cache después de ActionDispatch::Executor.
# Pasa el argumento { page_cache: false } a Lifo::Cache.
config.middleware.insert_after ActionDispatch::Executor, Lifo::Cache, page_cache: false

3.2.2 Intercambiando un Middleware

Puedes intercambiar un middleware existente en la pila de middleware usando config.middleware.swap.

# config/application.rb

# Reemplaza ActionDispatch::ShowExceptions con Lifo::ShowExceptions
config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions

3.2.3 Moviendo un Middleware

Puedes mover un middleware existente en la pila de middleware usando config.middleware.move_before y config.middleware.move_after.

# config/application.rb

# Mueve ActionDispatch::ShowExceptions antes de Lifo::ShowExceptions
config.middleware.move_before Lifo::ShowExceptions, ActionDispatch::ShowExceptions
# config/application.rb

# Mueve ActionDispatch::ShowExceptions después de Lifo::ShowExceptions
config.middleware.move_after Lifo::ShowExceptions, ActionDispatch::ShowExceptions

3.2.4 Eliminando un Middleware

Agrega las siguientes líneas a tu configuración de la aplicación:

# config/application.rb
config.middleware.delete Rack::Runtime

Y ahora, si inspeccionas la pila de middleware, encontrarás que Rack::Runtime no es parte de ella.

$ bin/rails middleware
(in /Users/lifo/Rails/blog)
use ActionDispatch::Static
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000001c304c8>
...
run Rails.application.routes

Si deseas eliminar middleware relacionado con sesiones, haz lo siguiente:

# config/application.rb
config.middleware.delete ActionDispatch::Cookies
config.middleware.delete ActionDispatch::Session::CookieStore
config.middleware.delete ActionDispatch::Flash

Y para eliminar middleware relacionado con el navegador,

# config/application.rb
config.middleware.delete Rack::MethodOverride

Si deseas que se genere un error cuando intentes eliminar un elemento inexistente, usa delete! en su lugar.

# config/application.rb
config.middleware.delete! ActionDispatch::Executor

3.3 Pila de Middleware Interno

Gran parte de la funcionalidad de Action Controller se implementa como Middlewares. La siguiente lista explica el propósito de cada uno de ellos:

ActionDispatch::HostAuthorization

  • Protege de ataques de re-binding de DNS permitiendo explícitamente los hosts a los que se puede enviar una solicitud. Consulta la guía de configuración para obtener instrucciones de configuración.

Rack::Sendfile

ActionDispatch::Static

Rack::Lock

  • Establece el indicador env["rack.multithread"] en false y envuelve la aplicación dentro de un Mutex.

ActionDispatch::Executor

  • Se utiliza para la recarga de código segura para hilos durante el desarrollo.

ActionDispatch::ServerTiming

  • Establece un encabezado Server-Timing que contiene métricas de rendimiento para la solicitud.

ActiveSupport::Cache::Strategy::LocalCache::Middleware

  • Se utiliza para el almacenamiento en caché en memoria. Este caché no es seguro para hilos.

Rack::Runtime

  • Establece un encabezado X-Runtime, que contiene el tiempo (en segundos) tomado para ejecutar la solicitud.

Rack::MethodOverride

  • Permite que el método sea sobrescrito si params[:_method] está establecido. Este es el middleware que soporta los tipos de métodos HTTP PUT y DELETE.

ActionDispatch::RequestId

  • Hace que un encabezado único X-Request-Id esté disponible para la respuesta y habilita el método ActionDispatch::Request#request_id.

ActionDispatch::RemoteIp

  • Verifica ataques de suplantación de IP.

Sprockets::Rails::QuietAssets

  • Suprime la salida del registrador para solicitudes de activos.

Rails::Rack::Logger

  • Notifica a los registros que la solicitud ha comenzado. Después de que la solicitud se completa, vacía todos los registros.

ActionDispatch::ShowExceptions

  • Rescata cualquier excepción devuelta por la aplicación y llama a una aplicación de excepciones que la envolverá en un formato para el usuario final.

ActionDispatch::DebugExceptions

  • Responsable de registrar excepciones y mostrar una página de depuración en caso de que la solicitud sea local.

ActionDispatch::ActionableExceptions

  • Proporciona una forma de despachar acciones desde las páginas de error de Rails.

ActionDispatch::Reloader

  • Proporciona callbacks de preparación y limpieza, destinados a ayudar con la recarga de código durante el desarrollo.

ActionDispatch::Callbacks

  • Proporciona callbacks para ser ejecutados antes y después de despachar la solicitud.

ActiveRecord::Migration::CheckPending

  • Verifica migraciones pendientes y genera ActiveRecord::PendingMigrationError si hay migraciones pendientes.

ActionDispatch::Cookies

  • Establece cookies para la solicitud.

ActionDispatch::Session::CookieStore

  • Responsable de almacenar la sesión en cookies.

ActionDispatch::Flash

  • Configura las claves de flash. Solo está disponible si config.session_store está establecido en un valor.

ActionDispatch::ContentSecurityPolicy::Middleware

  • Proporciona un DSL para configurar un encabezado Content-Security-Policy.

Rack::Head

  • Devuelve un cuerpo vacío para todas las solicitudes HEAD. Deja todas las demás solicitudes sin cambios.

Rack::ConditionalGet

  • Agrega soporte para "GET Condicional" para que el servidor responda con nada si la página no ha cambiado.

Rack::ETag

  • Agrega encabezado ETag en todos los cuerpos de tipo String. Los ETags se utilizan para validar caché.

Rack::TempfileReaper

  • Limpia archivos temporales utilizados para almacenar en búfer solicitudes multipart.

CONSEJO: Es posible usar cualquiera de los middlewares anteriores en tu pila de Rack personalizada.

4 Recursos

4.1 Aprendiendo Rack

4.2 Entendiendo Middlewares


Comentarios

Se te anima a ayudar a mejorar la calidad de esta guía.

Por favor contribuye si ves algún error tipográfico o errores fácticos. Para comenzar, puedes leer nuestra sección de contribuciones a la documentación.

También puedes encontrar contenido incompleto o cosas que no están actualizadas. Por favor agrega cualquier documentación faltante para main. Asegúrate de revisar Guías Edge primero para verificar si los problemas ya están resueltos o no en la rama principal. Revisa las Guías de Ruby on Rails para estilo y convenciones.

Si por alguna razón detectas algo que corregir pero no puedes hacerlo tú mismo, por favor abre un issue.

Y por último, pero no menos importante, cualquier tipo de discusión sobre la documentación de Ruby on Rails es muy bienvenida en el Foro oficial de Ruby on Rails.