AVISO: Este guia pressupõe um conhecimento básico do protocolo Rack e conceitos do Rack, como middlewares, mapas de URL e Rack::Builder
.
1 Introdução ao Rack
O Rack fornece uma interface mínima, modular e adaptável para desenvolver aplicações web em Ruby. Ao envolver as requisições e respostas HTTP da maneira mais simples possível, ele unifica e destila a API para servidores web, frameworks web e software intermediário (os chamados middlewares) em uma única chamada de método.
Explicar como o Rack funciona não está realmente no escopo deste guia. Caso você não esteja familiarizado com os conceitos básicos do Rack, você deve verificar a seção Recursos abaixo.
2 Rails no Rack
2.1 Objeto Rack da Aplicação Rails
Rails.application
é o objeto principal de aplicação Rack de uma aplicação Rails. Qualquer servidor web compatível com o Rack deve usar o objeto Rails.application
para servir uma aplicação Rails.
2.2 bin/rails server
bin/rails server
faz o trabalho básico de criar um objeto Rack::Server
e iniciar o servidor web.
Veja como bin/rails server
cria uma instância de Rack::Server
:
Rails::Server.new.tap do |server|
require APP_PATH
Dir.chdir(Rails.application.root)
server.start
end
O Rails::Server
herda de Rack::Server
e chama o método Rack::Server#start
desta forma:
class Server < ::Rack::Server
def start
# ...
super
end
end
2.3 rackup
Para usar o rackup
em vez do bin/rails server
do Rails, você pode colocar o seguinte dentro do arquivo config.ru
do diretório raiz da sua aplicação Rails:
# Rails.root/config.ru
require_relative "config/environment"
run Rails.application
E inicie o servidor:
$ rackup config.ru
Para saber mais sobre as diferentes opções do rackup
, você pode executar:
$ rackup --help
2.4 Desenvolvimento e Recarregamento Automático
Os middlewares são carregados uma vez e não são monitorados por alterações. Você precisará reiniciar o servidor para que as alterações sejam refletidas na aplicação em execução.
3 Pilha de Middlewares do Action Dispatcher
Muitos dos componentes internos do Action Dispatcher são implementados como middlewares do Rack. O Rails::Application
usa ActionDispatch::MiddlewareStack
para combinar vários middlewares internos e externos para formar uma aplicação Rails completa no Rack.
NOTA: ActionDispatch::MiddlewareStack
é o equivalente do Rails ao Rack::Builder
, mas é construído para melhor flexibilidade e mais recursos para atender aos requisitos do Rails.
3.1 Inspecionando a Pilha de Middlewares
O Rails possui um comando útil para inspecionar a pilha de middlewares em uso:
$ bin/rails middleware
Para uma aplicação Rails recém-gerada, isso pode produzir 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
Os middlewares padrão mostrados aqui (e alguns outros) são resumidos na seção Middlewares Internos, abaixo.
3.2 Configurando a Pilha de Middlewares
O Rails fornece uma interface de configuração simples config.middleware
para adicionar, remover e modificar os middlewares na pilha de middlewares através do arquivo application.rb
ou do arquivo de configuração específico do ambiente environments/<ambiente>.rb
.
3.2.1 Adicionando um Middleware
Você pode adicionar um novo middleware à pilha de middlewares usando um dos seguintes métodos:
config.middleware.use(new_middleware, args)
- Adiciona o novo middleware no final da pilha de middlewares.config.middleware.insert_before(existing_middleware, new_middleware, args)
- Adiciona o novo middleware antes do middleware existente especificado na pilha de middlewares.config.middleware.insert_after(existing_middleware, new_middleware, args)
- Adiciona o novo middleware após o middleware existente especificado na pilha de middlewares.
# config/application.rb
# Adiciona Rack::BounceFavicon no final
config.middleware.use Rack::BounceFavicon
# Adiciona Lifo::Cache após ActionDispatch::Executor.
# Passa o argumento { page_cache: false } para Lifo::Cache.
config.middleware.insert_after ActionDispatch::Executor, Lifo::Cache, page_cache: false
3.2.2 Trocando um Middleware
Você pode trocar um middleware existente na pilha de middlewares usando config.middleware.swap
.
# config/application.rb
# Substitui ActionDispatch::ShowExceptions por Lifo::ShowExceptions
config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions
3.2.3 Movendo um Middleware
Você pode mover um middleware existente na pilha de middlewares usando config.middleware.move_before
e config.middleware.move_after
.
# config/application.rb
# Move ActionDispatch::ShowExceptions para antes de Lifo::ShowExceptions
config.middleware.move_before Lifo::ShowExceptions, ActionDispatch::ShowExceptions
# config/application.rb
# Move ActionDispatch::ShowExceptions para depois de Lifo::ShowExceptions
config.middleware.move_after Lifo::ShowExceptions, ActionDispatch::ShowExceptions
3.2.4 Excluindo um Middleware
Adicione as seguintes linhas à configuração do seu aplicativo:
# config/application.rb
config.middleware.delete Rack::Runtime
Agora, se você inspecionar a pilha de middlewares, verá que Rack::Runtime
não faz mais parte dela.
$ bin/rails middleware
(in /Users/lifo/Rails/blog)
use ActionDispatch::Static
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000001c304c8>
...
run Rails.application.routes
Se você deseja remover middlewares relacionados à sessão, faça o seguinte:
# config/application.rb
config.middleware.delete ActionDispatch::Cookies
config.middleware.delete ActionDispatch::Session::CookieStore
config.middleware.delete ActionDispatch::Flash
E para remover middlewares relacionados ao navegador,
# config/application.rb
config.middleware.delete Rack::MethodOverride
Se você deseja que um erro seja gerado ao tentar excluir um item que não existe, use delete!
em vez disso.
# config/application.rb
config.middleware.delete! ActionDispatch::Executor
3.3 Pilha de Middlewares Internos
Grande parte da funcionalidade do Action Controller é implementada como Middlewares. A lista a seguir explica o propósito de cada um deles:
ActionDispatch::HostAuthorization
- Protege contra ataques de DNS rebinding, permitindo explicitamente os hosts para os quais uma solicitação pode ser enviada. Consulte o guia de configuração para obter instruções de configuração.
Rack::Sendfile
- Define o cabeçalho X-Sendfile específico do servidor. Configure isso por meio da opção
config.action_dispatch.x_sendfile_header
.
ActionDispatch::Static
- Usado para servir arquivos estáticos do diretório public. Desativado se
config.public_file_server.enabled
forfalse
.
Rack::Lock
- Define a flag
env["rack.multithread"]
comofalse
e envolve a aplicação em um Mutex.
ActionDispatch::Executor
- Usado para recarregar o código de forma segura em threads durante o desenvolvimento.
ActionDispatch::ServerTiming
- Define um cabeçalho
Server-Timing
contendo métricas de desempenho para a solicitação.
ActiveSupport::Cache::Strategy::LocalCache::Middleware
- Usado para cache em memória. Este cache não é thread-safe.
Rack::Runtime
- Define um cabeçalho X-Runtime, contendo o tempo (em segundos) necessário para executar a solicitação.
Rack::MethodOverride
- Permite que o método seja substituído se
params[:_method]
estiver definido. Este é o middleware que suporta os tipos de método HTTP PUT e DELETE.
ActionDispatch::RequestId
- Torna um cabeçalho
X-Request-Id
exclusivo disponível para a resposta e habilita o métodoActionDispatch::Request#request_id
.
ActionDispatch::RemoteIp
- Verifica ataques de spoofing de IP.
Sprockets::Rails::QuietAssets
- Suprime a saída do logger para solicitações de ativos.
Rails::Rack::Logger
- Notifica os logs de que a solicitação foi iniciada. Após a conclusão da solicitação, todos os logs são liberados.
ActionDispatch::ShowExceptions
- Resgata qualquer exceção retornada pela aplicação e chama um aplicativo de exceções que a envolverá em um formato para o usuário final.
ActionDispatch::DebugExceptions
- Responsável por registrar exceções e mostrar uma página de depuração caso a solicitação seja local.
ActionDispatch::ActionableExceptions
- Fornece uma maneira de despachar ações das páginas de erro do Rails.
ActionDispatch::Reloader
- Fornece callbacks de preparação e limpeza, destinados a auxiliar no recarregamento de código durante o desenvolvimento.
ActionDispatch::Callbacks
- Fornece callbacks a serem executados antes e depois de despachar a solicitação.
ActiveRecord::Migration::CheckPending
- Verifica migrações pendentes e gera um
ActiveRecord::PendingMigrationError
se houver migrações pendentes.
ActionDispatch::Cookies
- Define cookies para a solicitação.
ActionDispatch::Session::CookieStore
- Responsável por armazenar a sessão em cookies.
ActionDispatch::Flash
- Configura as chaves do flash. Disponível apenas se
config.session_store
estiver definido com um valor.
ActionDispatch::ContentSecurityPolicy::Middleware
- Fornece uma DSL para configurar um cabeçalho Content-Security-Policy.
Rack::Head
- Converte solicitações HEAD em solicitações
GET
e as serve como tal.
Rack::ConditionalGet
- Adiciona suporte para "Conditional
GET
" para que o servidor responda com nada se a página não foi alterada.
Rack::ETag
- Adiciona o cabeçalho ETag em todos os corpos de String. ETags são usados para validar o cache.
Rack::TempfileReaper
- Limpa os arquivos temporários usados para armazenar solicitações multipart.
DICA: É possível usar qualquer um dos middlewares acima em sua pilha personalizada do Rack.
4 Recursos
4.1 Aprendendo Rack
4.2 Entendendo Middlewares
Feedback
Você é incentivado a ajudar a melhorar a qualidade deste guia.
Por favor, contribua se encontrar algum erro de digitação ou factual. Para começar, você pode ler nossa contribuição à documentação seção.
Você também pode encontrar conteúdo incompleto ou desatualizado. Por favor, adicione qualquer documentação ausente para o principal. Certifique-se de verificar Guias Edge primeiro para verificar se os problemas já foram corrigidos ou não no branch principal. Verifique as Diretrizes dos Guias do Ruby on Rails para estilo e convenções.
Se por algum motivo você encontrar algo para corrigir, mas não puder corrigi-lo você mesmo, por favor abra uma issue.
E por último, mas não menos importante, qualquer tipo de discussão sobre a documentação do Ruby on Rails é muito bem-vinda no Fórum oficial do Ruby on Rails.