Se você mora na Terra, deve saber que o Rails Edge adotou o Rack. Mas, o que é esse tal de Rack?
O que é o Rack?
O Rack é uma interface entre servidores web e aplicações Ruby, baseada no padrão WSGI do Python. Ele possui diferentes handlers para os mais diversos webservers, como: Passenger, Mongrel, Thin, Ebb, Webrick, entre outros.
Ele é usado pelos principais frameworks Ruby: Merb, Sinatra, Ramaze, Waves, e outros. O Rails 2.3 virá com suporte à Rack. Ele também pode ser considerado um framework para construir frameworks. O Nyane é um bom exemplo disto, mas existem muitos outros.
Ele tem suporte à Middlewares que são como mini-funcionalidades que podem ser compartilhadas entre todos os frameworks que suportam Rack. Este artigo possui uma lista de diversos middlewares interessantes.
Através do Rack::Cascade é possível utilizar diferentes frameworks dentro de uma mesma aplicação.
Aplicações Rack
Uma aplicação Rack nada mais é do que um simples objeto Ruby (não precisa ser uma classe) que responde ao método call. Ele precisa de apenas um argumento, o environment e retorna um Array com três valores: O status (200, 404, 500), o header (’Content-Type’ => ‘text/html’, ’Location’ => ‘/’, ) e um objeto que responde ao método each (’uma string’).
Exemplos
O seguinte código é um exemplo de uma aplicação Rack:
class Hello
def call(env)
[ 200, {}, 'Hello World!' ]
end
end
Mas, como eu disse, não precisa ser uma classe, um simples lambda também é uma aplicação Rack válida:
lambda { |env| [200, {}, 'Hello World!' }
Isto é válido, porquê o método lambda retorna uma Proc, que responde pelo método call.
Nos dois exemplos, o retorno do método call é um Array com o status 200, headers em branco em uma string 'Hello World!'. Exatamente o que o Rack precisa para funcionar. :)
E esse environment, o que é?
O env (objeto passado ao método call), é um hash com diversas variáveis de ambientes, por exemplo: PATH_INFO, QUERY_STRING, REQUEST_METHOD, SERVER_PORT, entre outros.
E pra que ele serve?
Você usa o env para construir um objeto Rack::Request, que pode ser usado para obter os parâmetros GET e POST:
request = Rack::Request.new(env)
# returns the data received in the query string
request.GET
# returns the data received in the request body
request.POST
Eu sei receber um request, mas e como eu envio uma resposta?
O Rack::Response é usado para criar uma resposta HTTP. Com ele você pode configurar headers, criar cookies, entre outros:
# uma resposta simples
response = Rack::Response.new
response.status = 200
response.body("Hello World!")
response.finish
# um redirect
response = Rack::Response.new
response.status = 302
response.headers["Location"] = "/"
response.finish
# criando um cookie
response = Rack::Response.new
response.set_cookie('cookie-name', 'content')
response.finish
Rackup
O Rack vem com um binário chamado rackup que pode ser usado para servir aplicações Rack rapidamente. Ele lê arquivos .ru (não pode ser .rb), também chamados de “rack config files”, e usa o handler do Mongrel para servir a aplicação. Ele já adiciona os middlewares para Logging (Rack::CommonLogger) e Exceptions (Rack::ShowExceptions).
Exemplos
Usando uma classe:
class Hello
def call(env)
[ 200, {}, 'Hello World!' ]
end
end
run Hello.new
Um lambda:
run lambda {|env| [200, {}, "Hello World!"]}
Isso mesmo, não precisa de nenhum require. :) Para rodar, é simples:
rackup app.ru
Por padrão, ele rodará na porta 9292.
Ou, se você preferir, pode rodá-lo com o Thin:
thin start -R app.ru
Você também pode usar o Handler do Mongrel diretamente:
require "rubygems"
require "rack"
app = lambda { |env| [200, {}, 'Hello World!'] }
Rack::Handler::Mongrel.run(app, :Port => 3000)
Neste caso, o require é necessário.
Finalizando
Espero que este post tenha ajudado você a entender melhor o que é o Rack e o porquê dele ser importante no mundo Ruby. Nos próximos posts, irei explicar como construir e usar Middlewares, e falarei de uma das novas features do Rails que usa o Rack, o Metal, muito discutido nessa última semana.
20/12/08 às 1:27 pm #Diego Carrion
Acho que é o melhor artigo que ja vi que explica o que é o Rack, agora ficou muito simples de entender.
20/12/08 às 1:37 pm #Flávio Granero
Muito bem explicado, parabéns.
Fico esperando os próximos posts….
Abraço
20/12/08 às 2:45 pm #Jonas Galvez
O que ninguém quase nunca menciona é que Rack é diretamente baseado no padrão WSGI: http://www.python.org/dev/peps/pep-0333/
20/12/08 às 4:44 pm #Walter Cruz
Só faltou dizer que o rack foi uma idéia inspirada no WSGI do Python ;)
20/12/08 às 5:44 pm #Dirceu Pauka Jr.
Depois que você fez um framework acima do Rack ficou fácil saber explicar né? Massa cara! Execelente texto :)
20/12/08 às 7:40 pm #ArthurGeek
Jonas, Walter: Falha minha. Essa informação estava presente no post, mas na hora de revisar, acabei tirando e nem percebi. Corrigido! :)
22/12/08 às 12:01 pm #Carlos Brando
Ótimo artigo, muito explicativo!
26/12/08 às 7:04 pm #Eduardo Fiorezi
Excelente explicação Arthur. Gostei bastante.
11/01/10 às 5:40 pm #Itaquera
Ótimo post