Ruby on Rails "secuencia de bytes no válida en UTF-8" debido a bot
ruby-on-rails ruby-on-rails-3 (3)
Tengo algunos errores desencadenados por un bot chino: http://www.easou.com/search/spider.html cuando se desplaza por mis sitios web.
Las versiones de mis aplicaciones son todas con Ruby 1.9.3 y Rails 3.2.X
Aquí una stacktrace:
An ArgumentError occurred in listings#show:
invalid byte sequence in UTF-8
rack (1.4.5) lib/rack/utils.rb:104:in `normalize_params''
-------------------------------
Request:
-------------------------------
* URL : http://www.my-website.com
* IP address: X.X.X.X
* Parameters: {"action"=>"show", "controller"=>"listings", "id"=>"location-t7-villeurbanne--58"}
* Rails root: /.../releases/20140708150222
* Timestamp : 2014-07-09 02:57:43 +0200
-------------------------------
Backtrace:
-------------------------------
rack (1.4.5) lib/rack/utils.rb:104:in `normalize_params''
rack (1.4.5) lib/rack/utils.rb:96:in `block in parse_nested_query''
rack (1.4.5) lib/rack/utils.rb:93:in `each''
rack (1.4.5) lib/rack/utils.rb:93:in `parse_nested_query''
rack (1.4.5) lib/rack/request.rb:332:in `parse_query''
actionpack (3.2.18) lib/action_dispatch/http/request.rb:275:in `parse_query''
rack (1.4.5) lib/rack/request.rb:209:in `POST''
actionpack (3.2.18) lib/action_dispatch/http/request.rb:237:in `POST''
actionpack (3.2.18) lib/action_dispatch/http/parameters.rb:10:in `parameters''
-------------------------------
Session:
-------------------------------
* session id: nil
* data: {}
-------------------------------
Environment:
-------------------------------
* CONTENT_LENGTH : 514
* CONTENT_TYPE : application/x-www-form-urlencoded
* HTTP_ACCEPT : text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
* HTTP_ACCEPT_ENCODING : gzip, deflate
* HTTP_ACCEPT_LANGUAGE : zh;q=0.9,en;q=0.8
* HTTP_CONNECTION : close
* HTTP_HOST : www.my-website.com
* HTTP_REFER : http://www.my-website.com/
* HTTP_USER_AGENT : Mozilla/5.0 (compatible; EasouSpider; +http://www.easou.com/search/spider.html)
* ORIGINAL_FULLPATH : /
* PASSENGER_APP_SPAWNER_IDLE_TIME : -1
* PASSENGER_APP_TYPE : rack
* PASSENGER_CONNECT_PASSWORD : [FILTERED]
* PASSENGER_DEBUGGER : false
* PASSENGER_ENVIRONMENT : production
* PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME : -1
* PASSENGER_FRIENDLY_ERROR_PAGES : true
* PASSENGER_GROUP :
* PASSENGER_MAX_REQUESTS : 0
* PASSENGER_MIN_INSTANCES : 1
* PASSENGER_SHOW_VERSION_IN_HEADER : true
* PASSENGER_SPAWN_METHOD : smart-lv2
* PASSENGER_USER :
* PASSENGER_USE_GLOBAL_QUEUE : true
* PATH_INFO : /
* QUERY_STRING :
* REMOTE_ADDR : 183.60.212.153
* REMOTE_PORT : 52997
* REQUEST_METHOD : GET
* REQUEST_URI : /
* SCGI : 1
* SCRIPT_NAME :
* SERVER_PORT : 80
* SERVER_PROTOCOL : HTTP/1.1
* SERVER_SOFTWARE : nginx/1.2.6
* UNION_STATION_SUPPORT : false
* _ : _
* action_controller.instance : listings#show
* action_dispatch.backtrace_cleaner : #<Rails::BacktraceCleaner:0x000000056e8660>
* action_dispatch.cookies : #<ActionDispatch::Cookies::CookieJar:0x00000006564e28>
* action_dispatch.logger : #<ActiveSupport::TaggedLogging:0x0000000318aff8>
* action_dispatch.parameter_filter : [:password, /RAW_POST_DATA/, /RAW_POST_DATA/, /RAW_POST_DATA/]
* action_dispatch.remote_ip : 183.60.212.153
* action_dispatch.request.content_type : application/x-www-form-urlencoded
* action_dispatch.request.parameters : {"action"=>"show", "controller"=>"listings", "id"=>"location-t7-villeurbanne--58"}
* action_dispatch.request.path_parameters : {:action=>"show", :controller=>"listings", :id=>"location-t7-villeurbanne--58"}
* action_dispatch.request.query_parameters : {}
* action_dispatch.request.request_parameters : {}
* action_dispatch.request.unsigned_session_cookie: {}
* action_dispatch.request_id : 9f8afbc8ff142f91ddbd9cabee3629f3
* action_dispatch.routes : #<ActionDispatch::Routing::RouteSet:0x0000000339f370>
* action_dispatch.show_detailed_exceptions : false
* action_dispatch.show_exceptions : true
* rack-cache.allow_reload : false
* rack-cache.allow_revalidate : false
* rack-cache.cache_key : Rack::Cache::Key
* rack-cache.default_ttl : 0
* rack-cache.entitystore : rails:/
* rack-cache.ignore_headers : ["Set-Cookie"]
* rack-cache.metastore : rails:/
* rack-cache.private_headers : ["Authorization", "Cookie"]
* rack-cache.storage : #<Rack::Cache::Storage:0x000000039c5768>
* rack-cache.use_native_ttl : false
* rack-cache.verbose : false
* rack.errors : #<IO:0x000000006592a8>
* rack.input : #<PhusionPassenger::Utils::RewindableInput:0x0000000655b3a0>
* rack.multiprocess : true
* rack.multithread : false
* rack.request.cookie_hash : {}
* rack.request.form_hash :
* rack.request.form_input : #<PhusionPassenger::Utils::RewindableInput:0x0000000655b3a0>
* rack.request.form_vars : ���W�"��陷q�B��)���
�F��P Z� 8�� & G/y�P��u�T ed �.�%�mxEAẳ/�d*�Hg� �C賳�lj��� � U 1��]pgt�P�
Ɗ ��c"� ��LX��D���HR�y��p`6�l���lN�P �l�S����`V4y��c����X2� &JO!��*p �l��-�гU��w }g�ԍk�� (� F J�� q�:�5G�Jh�pί����ࡃ] �z�h���� d }�}
* rack.request.query_hash : {}
* rack.request.query_string :
* rack.run_once : false
* rack.session : {}
* rack.session.options : {:path=>"/", :domain=>nil, :expire_after=>nil, :secure=>false, :httponly=>true, :defer=>false, :renew=>false, :coder=>#<Rack::Session::Cookie::Base64::Marshal:0x000000034d4ad8>, :id=>nil}
* rack.url_scheme : http
* rack.version : [1, 0]
Como puede ver, no existe un utf-8 no válido en la url pero solo en el rack.request.form_vars
. Tengo alrededor de cien errores por día, y todos similares a este.
Entonces, intenté forzar utf-8 en rack.request.form_vars
con algo como esto:
class RackFormVarsSanitizer
def initialize(app)
@app = app
end
def call(env)
if env["rack.request.form_vars"]
env["rack.request.form_vars"] = env["rack.request.form_vars"].force_encoding(''UTF-8'')
end
@app.call(env)
end
end
Y lo llamo en mi application.rb
:
config.middleware.use "RackFormVarsSanitizer"
No parece funcionar porque ya tengo errores. El problema es que no puedo probar en modo de desarrollo porque no sé cómo configurar rack.request.form_vars
.
utf8-cleaner
gema utf8-cleaner
pero no soluciona nada.
Alguien tiene una idea para arreglar esto? o para activarlo en el desarrollo?
Agregue esta línea a su Gemfile
, luego ejecute bundle
en su terminal:
gem "handle_invalid_percent_encoding_requests"
Esta solución se basa en la respuesta de Henrik , convertida en una gema de Rails Engine .
Entonces no tienes que armar los comentarios en mi otra respuesta, esto es lo que estoy haciendo ahora. No he visto ningún error durante 24 horas, así que parece muy prometedor:
Agrega rack-utf8_sanitizer a tu Gemfile:
gem ''rack-utf8_sanitizer''
y correr
bundle
Coloque este middleware en la app/middleware/handle_invalid_percent_encoding.rb
y cambie el nombre de la clase HandleInvalidPercentEncoding
(porque ExceptionApp
es un poco demasiado general).
En el bloque de config/application.rb
de config/application.rb
do:
require "#{Rails.root}/app/middleware/handle_invalid_percent_encoding.rb"
# NOTE: These must be in this order relative to each other.
# HandleInvalidPercentEncoding just raises for encoding errors it doesn''t cover,
# so it must run after (= be inserted before) Rack::UTF8Sanitizer.
config.middleware.insert 0, HandleInvalidPercentEncoding
config.middleware.insert 0, Rack::UTF8Sanitizer # from a gem
Desplegar. Hecho.
(La app
es la ubicación de middleware en el proyecto en el que estoy trabajando, pero probablemente preferiría lib
. Lo que sea, cualquiera debería funcionar).
Hay un problema en el repositorio de gemas con un enlace a la posible solución de alguien : dicen que funciona para ellos, pero no están seguros de si es una buena solución.
Todavía tengo que intentarlo, pero creo que lo haré.