edge
Más en rubyonrails.org: Más Ruby on Rails

Rails en Rack

Esta guía cubre la integración de Rails con Rack y la interfaz 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 las solicitudes y respuestas HTTP de la manera más simple posible, unifica y destila la API para servidores web, frameworks web y software intermedio (llamado middleware) en una sola llamada de método.

Explicar cómo funciona Rack no está realmente dentro del 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 Recursos a continuación.

2 Rails en 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 se encarga de crear un objeto Rack::Server y de iniciar 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

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 agregar 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 luego iniciar 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 supervisan los cambios. Debes reiniciar el servidor para que los cambios se reflejen en la aplicación en ejecución.

3 Pila de Middlewares de Action Dispatcher

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

NOTA: ActionDispatch::MiddlewareStack es el equivalente de Rails a Rack::Builder, pero está diseñado para ofrecer una mayor flexibilidad y más características para cumplir con los requisitos de Rails.

3.1 Inspeccionar la pila de Middlewares

Rails tiene un comando útil para inspeccionar la pila de middlewares 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 mostrados aquí (y algunos otros) se resumen en la sección Middlewares internos a continuación.

3.2 Configurar la pila de Middlewares

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

3.2.1 Agregar un Middleware

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

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

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

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

# config/application.rb

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

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

3.2.2 Intercambiar un Middleware

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

# config/application.rb

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

3.2.3 Mover un Middleware

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

# config/application.rb

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

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

3.2.4 Eliminar un Middleware

Agregue las siguientes líneas a la configuración de su aplicación:

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

Y ahora, si inspecciona la pila de middlewares, verá que Rack::Runtime no forma 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 desea eliminar middlewares relacionados con la sesión, haga lo siguiente:

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

Y para eliminar middlewares relacionados con el navegador,

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

Si desea que se genere un error cuando intente eliminar un elemento que no existe, use delete! en su lugar.

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

3.3 Pila interna de middlewares

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 contra ataques de reasignación de DNS al permitir explícitamente los hosts a los que se puede enviar una solicitud. Consulte la guía de configuración para obtener instrucciones de configuración.

Rack::Sendfile

ActionDispatch::Static

Rack::Lock

  • Establece la bandera env["rack.multithread"] en false y envuelve la aplicación en un Mutex.

ActionDispatch::Executor

  • Se utiliza para la recarga de código segura para subprocesos 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. Esta caché no es segura para subprocesos.

Rack::Runtime

  • Establece un encabezado X-Runtime que contiene el tiempo (en segundos) que tarda en ejecutarse la solicitud.

Rack::MethodOverride

  • Permite que se anule el método si se establece params[:_method]. Este es el middleware que admite los tipos de método 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 los ataques de suplantación de IP.

Sprockets::Rails::QuietAssets

  • Suprime la salida del registro para las solicitudes de activos.

Rails::Rack::Logger

  • Notifica a los registros que la solicitud ha comenzado. Después de que se completa la solicitud, se vacían 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 devoluciones de llamada de preparación y limpieza, destinadas a ayudar con la recarga de código durante el desarrollo.

ActionDispatch::Callbacks

  • Proporciona devoluciones de llamada que se ejecutarán antes y después de despachar la solicitud.

ActiveRecord::Migration::CheckPending

  • Verifica las migraciones pendientes y genera un error 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 se establece en un valor.

ActionDispatch::ContentSecurityPolicy::Middleware

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

Rack::Head

  • Convierte las solicitudes HEAD en solicitudes GET y las sirve como tal.

Rack::ConditionalGet

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

Rack::ETag

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

Rack::TempfileReaper

  • Limpia los archivos temporales utilizados para almacenar las solicitudes multipartes.

CONSEJO: Es posible utilizar cualquiera de los middlewares anteriores en su pila personalizada de Rack.

4 Recursos

4.1 Aprendiendo Rack

4.2 Entendiendo los Middlewares

Comentarios

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

Por favor, contribuye si encuentras algún error tipográfico o factual. Para empezar, puedes leer nuestra contribución a la documentación sección.

También puedes encontrar contenido incompleto o desactualizado. Por favor, añade cualquier documentación faltante para main. Asegúrate de revisar Edge Guides primero para verificar si los problemas ya están resueltos o no en la rama principal. Consulta las Directrices de las Guías de Ruby on Rails para el estilo y las convenciones.

Si por alguna razón encuentras algo que corregir pero no puedes solucionarlo tú mismo, por favor abre un problema.

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