O Carlos Brando vem fazendo um excelente trabalho em trazer para nós as novidades do Rails Edge (no caso, o 2.2). Mas ao me deparar com esta atualização não pude me conter em blogar sobre. Na verdade, apenas traduzir o artigo do Ryan.

———–

Conditional-gets são uma facilidade da especificação do HTTP que fornece um método de os servidores we comunicarem aos brosers que a resposta para a requisição GET não mudou desde a última requisição e que o cache do browser pode ser usado com segurança.

Eles funcionam usando os cabeçalhos HTTP_IF_NONE_MATCH e HTTP_IF_MODIFIED_SINCE para passar para frente e para trás um identificador único do conteúdo e o timestamp de quando o conteúdo foi modificado pela última vez. Se o browser fizer a requisição onde o identificador do conteúdo (etag) ou a data da última modificação bater com a versão do servidor então o servidor precisa apenas enviar de volta uma resposta vazia com um status de “não modificado” (304).

É do servidor (nós) a responsabilidade de olhar a data da última modificação e o cabeçalho if-none-match e determinar quando ou não enviar a resposta completa (com a renderização da página, por exemplo). Com este novo suporte a conditional-get no rails, isto se torna uma tarefa muito fácil:

class ArticlesController < ApplicationController
    def show
        @article = Article.find(params[:id])
 
        # Define o cabeçalho da resposta para refletir exatamente
        # o estado do objeto requisitado
        response.last_modified = @article.published_at.utc
        response.etag = @article
 
        # Se o estado da requisição é o mesmo do estado no servidor
        # então sabemos que não precisamos enviar todo o resultado
        if request.fresh?(response)
          head :not_modified
        else
          respond_to do |wants|
            # normal response processing
          end
        end
    end
end

O valor do etag é calculado para você com o metodo setter etag=. Tudo que você tem que fazer é prover um único objeto ou array de objetos que definem de forma única a identificação desta requisição. Neste exemplo o artigo por si mesmo contém toda a informação que identifica o estado desta requisição. De qualquer forma, você pode precisar de usar mais de uma chave em seu aplicativo. Como para uma requisição específica para cada usuário:

response.etag = [@article, current_user]

O método request.fresh?(response) é quem dirá a você se a requisição casa com o valor de last-modified-since ou if-none-match da resposta que está sendo enviada. Se sim, você pode evitar de responder todo o conteúdo e economizar alguma (ou muita!) banda.

Também é possível você evitar de acessar o banco de dados se seu aplicativo trata com páginas completamente estáticas armazenadas no banco de dados (isso é raro):

class ArticlesController < ApplicationController
    def show
        # Se o artigo não muda, o etag pode se basear apenas em
        # ítems que temos na requisição
        response.etag = [:article, params[:id]]
 
        # Se o estado da requisição é o mesmo do servidor
        # podemos evitar também de acessar o banco de dados
        if request.fresh?(response)
          head :not_modified
        else
          @article = Article.find(params[:id])
          respond_to do |wants|
            ...
          end
        end
    end
end

Então, seja um bom cidadão e faça suas requisições compatíveis com conditional-get. Isto é a coisa certa a ser feita – e melhoram também a performance de seus programas.

—-

Vale notar, que você pode também usar estes cabeçalhos para acessar webservices (principalmente os feitos em Rails agora :D ) fazendo requisição de XML, se você, por exemplo, estiver guardando os dados que você acessou e guardar a data em que isto foi feito, assim você economisa ainda mais banda!

1 Comentário

  1. [...] Carlos J?nior j? escreveu sobre isto no blog da milk-it. Provavelmente teremos suporte a ETags no Rails 2.2. Eu disse provavelmente porque isto ainda n?o [...]

Deixe seu comentário


  • Deseja alterar a sua imagem de exibição? Faça uma conta no Gravatar.