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…