title: Ruby on Rails "invalid byte sequence in UTF-8" due to bot
body: <p>I have some errors triggered by a chinese bot: <a href="http://www.easou.com/search/spider.html">http://www.easou.com/search/spider.html</a> when it scrolls my websites.</p>
  
  <p>Versions of my applications are all with Ruby 1.9.3 and Rails 3.2.X</p>
  
  <p>Here a stacktrace :</p>
  
  <pre><code>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"=&gt;"show", "controller"=&gt;"listings", "id"=&gt;"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              : #&lt;Rails::BacktraceCleaner:0x000000056e8660&gt;
    * action_dispatch.cookies                        : #&lt;ActionDispatch::Cookies::CookieJar:0x00000006564e28&gt;
    * action_dispatch.logger                         : #&lt;ActiveSupport::TaggedLogging:0x0000000318aff8&gt;
    * 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"=&gt;"show", "controller"=&gt;"listings", "id"=&gt;"location-t7-villeurbanne--58"}
    * action_dispatch.request.path_parameters        : {:action=&gt;"show", :controller=&gt;"listings", :id=&gt;"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                         : #&lt;ActionDispatch::Routing::RouteSet:0x0000000339f370&gt;
    * 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                             : #&lt;Rack::Cache::Storage:0x000000039c5768&gt;
    * rack-cache.use_native_ttl                      : false
    * rack-cache.verbose                             : false
    * rack.errors                                    : #&lt;IO:0x000000006592a8&gt;
    * rack.input                                     : #&lt;PhusionPassenger::Utils::RewindableInput:0x0000000655b3a0&gt;
    * rack.multiprocess                              : true
    * rack.multithread                               : false
    * rack.request.cookie_hash                       : {}
    * rack.request.form_hash                         :
    * rack.request.form_input                        : #&lt;PhusionPassenger::Utils::RewindableInput:0x0000000655b3a0&gt;
    * rack.request.form_vars                         : ���W�"��陷q�B��)���
  �F��P   Z� 8�� &amp;   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�        &amp;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=&gt;"/", :domain=&gt;nil, :expire_after=&gt;nil, :secure=&gt;false, :httponly=&gt;true, :defer=&gt;false, :renew=&gt;false, :coder=&gt;#&lt;Rack::Session::Cookie::Base64::Marshal:0x000000034d4ad8&gt;, :id=&gt;nil}
    * rack.url_scheme                                : http
    * rack.version                                   : [1, 0]
  </code></pre>
  
  <p>As you can see there is no invalid utf-8 in the url but only in the <code>rack.request.form_vars</code> . I have about hundred errors per days, and all similar as this one.</p>
  
  <p>So, I tried to force utf-8 in <code>rack.request.form_vars</code> with something like this:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>And I call it in my <code>application.rb</code> :</p>
  
  <pre><code>config.middleware.use "RackFormVarsSanitizer"
  </code></pre>
  
  <p>It doesn't seem to work because I already have errors. The problem is I can't test in development mode because I don't know how to set <code>rack.request.form_vars</code>. </p>
  
  <p>I installed <code>utf8-cleaner</code> gem but it fixes nothing.</p>
  
  <p>Somebody have an idea to fix this? or to trigger it in development?</p>