Archive for September, 2009

Superguia Rack – Parte 2 – Dissecando o Rack

Continuando nossa saga iniciada no post anterior, voltaremos ao exemplo do HelloWorld para entendermos mais profundamente a estrutura de um objeto Rack. Como mencionado anteriormente, um este objeto deve possuir (na verdade responder a) um método call(env), retornando em sua resposta um array com 3 elementos. Veremos mais profundamente cada um desses elementos.

class HelloWorld
  def call(env)
    [200, {"Content-Type" => "text/html"}, "Hello World"]
  end
end

O método def call(env)

Env

O parâmetro recebido pelo método call é uma hash com as propriedades do ambiente do visitante da aplicação. Se alterarmos o nosso HelloWorld para imprimir o objeto env ao invés da string, teremos algo parecido com isso:

{
"REQUEST_METHOD"=>"GET",
"REQUEST_PATH"=>"/",
"REQUEST_URI"=>"/",
"HTTP_VERSION"=>"HTTP/1.1",
"HTTP_HOST"=>"localhost:9292",
"HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/530.18 (KHTML, like Gecko) Version/4.0.1 Safari/530.18",
"HTTP_ACCEPT"=>"application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5", "HTTP_ACCEPT_LANGUAGE"=>"en-us", "HTTP_ACCEPT_ENCODING"=>"gzip,deflate",
"HTTP_CONNECTION"=>"keep-alive", "GATEWAY_INTERFACE"=>"CGI/1.2",
"SERVER_NAME"=>"localhost",
"SERVER_PORT"=>"9292",
"SERVER_PROTOCOL"=>"HTTP/1.1",
"SERVER_SOFTWARE"=>"Mongrel 1.1.5",
 "PATH_INFO"=>"/",
 "SCRIPT_NAME"=>"",
 "REMOTE_ADDR"=>"127.0.0.1", "rack.version"=>[0, 1], "rack.input"=>#, "rack.errors"=>#>, "rack.multithread"=>true, "rack.multiprocess"=>false, "rack.run_once"=>false, "rack.url_scheme"=>"http",
 "QUERY_STRING"=>""}
 

Dentre as informações impressas, algumas são bem importantes, como:

  • REQUEST_METHOD: Informa qual o verbo HTTP (GET, PUT, DELETE…) usado pelo usuário ao acessar a página.
  • HTTP_USER_AGENT: Informa o browser do usuário, facilitando o tratamento para browsers diferente em sua aplicação.
  • QUERY_STRING: Informa os argumentos passados após o “?” da url, útil para fazer parsing dos parâmetros.

Status

O primeiro objeto retornado no array de resposta é um inteiro, representando o status da resposta que sua aplicação retornará no método. O 200 do nosso exemplo, representa “OK” segundo a especificação do HTTP. É aqui seu controle de exceção jogará aquele lindo “Erro 404″ quando o usuário digitar incorretamente um sub-caminho de sua aplicação. ;-)

HTTP Headers

Cabeçalhos HTTP informam o tipo de retorno do pacote. O segundo objeto do nosso retorno deve OBRIGATORIAMENTE responder a um método “each” e devolver chaves e valores de seus elementos, tipicamente um Hash, como no nosso exemplo. A chave Content-Type, por exemplo, deve retornar o tipo de retorno a ser esperado, podendo ser HTML(“Content-Type” => “text/html”), XML, MP3 (‘Content-Type’ => ‘audio/mp3′), entre outros.

Response Body

O retorno “Body” deve responder ao método each retornando um array de strings. Este será o conteúdo que será apresentado ao usuário no navegador.

ATENÇÃO: Segundo a documentação atual do Rack, o Body não deve mais ser uma simples string(como nos exemplos do post anterior). Aparentemente isto quebrará no Ruby 1.9.

Rack:Builder

É uma ferramenta que nos permite construir aplicações Rack utilizando uma DSL para “costurar” diferentes middlewares e aplicações. Os Builders são os parafusos das estantes, ou a cola que une as estruturas separadas criando uma inteiramente nova. Na verdade, o Builder é o cara que torna o a idéia do Rack tão genial. A facilidade que ele proporciona na criação de Middlewares ficará bem claro no próximo post.

Os métodos fornecidos pela DSL do Buider são:

Read more…

Superguia Rack – Parte 1

Este é o primeiro de uma série de posts dedicado ao Rack. No início, Rack me parecia muito obscuro e estes posts serão criados com o intuito de clarear as idéias de quem ainda possui dificuldade para entender este pequeno framework.

Introdução da Introdução

Em fevereiro de 2007, Christian Neukirchen postou em seu blog um artigo chamado “Introduzindo Rack” no qual falava sobre a quantidade de código duplicado que ele achava em diferentes Frameworks Web escritos em Ruby. Ao anunciar a sua criação, o autor tocava em um ponto importante aonde escrevia, com razão, sobre um assunto que na verdade não era culpa dos desenvolvedores.

Sendo todos frameworks web, era de se esperar que muitas coisas fossem parecidas. A grande sacada do criador de Rack, foi o fato de ter percebido que web pode, em grande parte, ser resumida como uma série de requisições e respostas HTTP. O resto é framework que vai por cima.

HTTP pode ser resumido de maneira muito simples, como uma série de REQUESTS e RESPONSES. Rack utiliza-se muito bem dessa “simplicidade” para encapsular praticamente todo o controle dessa troca de mensagens em um objeto Ruby. Ao encapsular as requisições HTTP, Rack é capaz de prover interfaces para aplicações entre web servers, web frameworks e middlewares.

O que é Rack?

Podemos considerar o Rack uma especificação para a criação de aplicações web desenvolvidas com ruby. Segundo Dan Webb em sua apresentação “8 minutes on Rack“:

“Se você tem um objeto Ruby que possui um método call cujo o único argumento é env e retorna um array com 3 elementos ([200, {"Content-Type" => "text/html"}, "Hello World!"] ), então ele pode ser conectado a qualquer web server que suporte Rack”

Mas a definição mais simples possível é a que Rack provê uma interface mínima entre web servers e web frameworks escritos em Ruby.
Read more…