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: MerbSinatraRamazeWaves, 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.

/ Trackback URI: trackback

9 comentários em “Então, o Rails agora usa Rack. Mas o que é o Rack?”

  1. 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.

  2. 20/12/08 às 1:37 pm #Flávio Granero

    Muito bem explicado, parabéns.

    Fico esperando os próximos posts….

    Abraço

  3. 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/

  4. 20/12/08 às 4:44 pm #Walter Cruz

    Só faltou dizer que o rack foi uma idéia inspirada no WSGI do Python ;)

  5. 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 :)

  6. 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! :)

  7. 22/12/08 às 12:01 pm #Carlos Brando

    Ótimo artigo, muito explicativo!

  8. 26/12/08 às 7:04 pm #Eduardo Fiorezi

    Excelente explicação Arthur. Gostei bastante.

  9. 11/01/10 às 5:40 pm #Itaquera

    Ótimo post

Deixe um comentário

Não é aceito código HTML