terça-feira, 22 de março de 2011

Corrigindo o enconding retornado pelo Net::HTTP do ruby 1.9

A String retornada pelo Net::HTTP.get no ruby 1.9 sempre é definida com encoding "ASCII-8BIT". Acontece que muitas vezes esse não é o encoding correto da String, e portanto, erros esquisitos podem acontecer. Um exemplo pode ser visto abaixo quando utilizei essa String em um erb:

invalid byte sequence in UTF-8

Ou o seguinte, que acontece ao tentar encodar essa String para UTF-8:

> minha_string.encode("UTF-8")
Encoding::UndefinedConversionError: "\xC3" from ASCII-8BIT to UTF-8

A solução para este problema é antes de encodar, definir o encoding correto da String. Para isso podemos utilizar o header "content-type" retornado na requisição. Se por exemplo ele retornasse 'text/xml; charset=ISO-8859-1', podemos converter a String da seguinte forma:

> minha_string.force_encoding("ISO-8859-1").encode("UTF-8")

Para não ter que fazer isso a cada requisição HTTP, criei uma lib que altera o metodo body do HttpResponse. O código pode ser pego aqui:

http://gist.github.com/882465

Eu até pensei em alterar o metodo force_encoding da String para aceitar o valor do content-type, mas achei que isso seria dar muita responsabilidade para a String. Como o valor de content-type está apenas no ambito do HTTP, faz sentido colocar na classe Net::HttpResponse.