We have a Turkish website and some old links are crawled by some search engines. The links seem to be malformed or cannot be processed and therefore causing ActionController::BadRequest error. On the local machine with development env this causes to return the Rails error page with ActionController::BadRequest.
But on the Server we get an 500 server error. This issues is discussed on several other pages like here. But none of the solutions helped.
In both cases we would like to redirect to a page not found-page.
I already tried to rescue_from ActionController::BadRequest and rescue_from ActionController::RoutingError in ApplicationController because of the aforementioned article, where they state that BadRequest turns into RoutingError.
But neither of them worked.
I hope someone had the same problem and already resolved it. Thanks in advance for your answers.
Edit:
One example problem-url is http://localhost:3000/Di%c5%ef%bf%bd-f%c4%b1r%c3%a7as%c4%b1.
Terminal output:
ActionController::BadRequest (ActionController::BadRequest):
actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:37:in `block in call'
actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:33:in `each'
actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:33:in `call'
actionpack (4.0.0) lib/action_dispatch/journey/router.rb:71:in `block in call'
actionpack (4.0.0) lib/action_dispatch/journey/router.rb:59:in `each'
actionpack (4.0.0) lib/action_dispatch/journey/router.rb:59:in `call'
actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:655:in `call'
newrelic_rpm (3.6.4.122) lib/new_relic/rack/error_collector.rb:12:in `call'
newrelic_rpm (3.6.4.122) lib/new_relic/rack/agent_hooks.rb:22:in `call'
newrelic_rpm (3.6.4.122) lib/new_relic/rack/browser_monitoring.rb:16:in `call'
newrelic_rpm (3.6.4.122) lib/new_relic/rack/developer_mode.rb:28:in `call'
rack (1.5.2) lib/rack/etag.rb:23:in `call'
rack (1.5.2) lib/rack/conditionalget.rb:25:in `call'
rack (1.5.2) lib/rack/head.rb:11:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/params_parser.rb:27:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/flash.rb:241:in `call'
rack (1.5.2) lib/rack/session/abstract/id.rb:225:in `context'
rack (1.5.2) lib/rack/session/abstract/id.rb:220:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/cookies.rb:486:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
activesupport (4.0.0) lib/active_support/callbacks.rb:373:in `_run__4278100521352222029__call__callbacks'
activesupport (4.0.0) lib/active_support/callbacks.rb:80:in `run_callbacks'
actionpack (4.0.0) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/reloader.rb:64:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/remote_ip.rb:76:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'
rollbar (0.11.7) lib/rollbar/middleware/rails/show_exceptions.rb:19:in `call_with_rollbar'
actionpack (4.0.0) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
railties (4.0.0) lib/rails/rack/logger.rb:38:in `call_app'
railties (4.0.0) lib/rails/rack/logger.rb:21:in `block in call'
activesupport (4.0.0) lib/active_support/tagged_logging.rb:67:in `block in tagged'
activesupport (4.0.0) lib/active_support/tagged_logging.rb:25:in `tagged'
activesupport (4.0.0) lib/active_support/tagged_logging.rb:67:in `tagged'
railties (4.0.0) lib/rails/rack/logger.rb:21:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/request_id.rb:21:in `call'
rack (1.5.2) lib/rack/methodoverride.rb:21:in `call'
rack (1.5.2) lib/rack/runtime.rb:17:in `call'
activesupport (4.0.0) lib/active_support/cache/strategy/local_cache.rb:83:in `call'
rack (1.5.2) lib/rack/lock.rb:17:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/static.rb:64:in `call'
railties (4.0.0) lib/rails/engine.rb:511:in `call'
railties (4.0.0) lib/rails/application.rb:97:in `call'
rack (1.5.2) lib/rack/content_length.rb:14:in `call'
puma (2.6.0) lib/puma/server.rb:486:in `handle_request'
puma (2.6.0) lib/puma/server.rb:357:in `process_client'
puma (2.6.0) lib/puma/server.rb:250:in `block in run'
puma (2.6.0) lib/puma/thread_pool.rb:92:in `call'
puma (2.6.0) lib/puma/thread_pool.rb:92:in `block in spawn_thread'
Best regards
I had the exact same issue in a Rails 4.0.x app where it was polluting my New Relic error page.
I got around this by writing a middleware that caches the ActionController::BadRequest error, Logs it and returns a 400 error page. (A 400 seemed more appropriate then a 404 error.)
app/middleware/catch_request_errors.rb
class CatchRequestErrors
def initialize(app)
@app = app
end
def call(env)
begin
@app.call(env)
rescue ActionController::BadRequest => error
::Rails.logger.warn("WARN: 400 ActionController::BadRequest: #{env['REQUEST_URI']}")
@html_400_page ||= File.read(::Rails.root.join('public', '400.html'))
[
400, { "Content-Type" => "text/html" },
[ @html_400_page ]
]
end
end
end
config/application.rb
config.middleware.insert_before ActionDispatch::ParamsParser, "CatchRequestErrors"
public/400.html
<!DOCTYPE html>
<html>
<head>
<title>Your request could not be handled (400)</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 25em;
padding: 0 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
<body>
<!-- This file lives in public/400.html -->
<div class="dialog">
<h1>Your request could not be handled.</h1>
<p>Please check the url and post data for syntax errors.</p>
</div>
</body>
</html>
This stops processing the rails stack, logs the error and returns the 400.html page to the user freeing the app to process a more valid request.
I'm also caching the 400 page as a instance variable to save on GC and Disc IO.
I suppose that one of your routes or Rack middleware is invalid and causes the 500 error. In new Rails app there is no incorrect behaviour with url http://localhost:3000/Di%c5%ef%bf%bd-f%c4%b1r%c3%a7as%c4%b1 - app returns a 404 error as expected. Also request to http://127.0.0.1:3000/?foo[]=array&foo[hash]=hash return absolutely correct response with 400 error (BadRequest).
Try to rewrite routes like this:
Rails.application.routes.draw do
get '/*path', :to => lambda { |env| [200, {}, [env.to_s]]}
# omited
end
and take a look to response status - if it 200, than problem in your Rails application, otherwise anywhere else in the rack middleware.
rails -v #=> Rails 4.1.1
There is a hack. Put this code inside initializers
module Rack
module Utils
alias_method :original_normalize_params, :normalize_params
module_function :original_normalize_params
def normalize_params(params, name, v = nil)
begin
original_normalize_params(params, name, v)
rescue => e
raise ActionController::BadRequest.new("Incorrect URL")
end
end
module_function :normalize_params
end
end
It will respond with 400 for requests like http://127.0.0.1:3000/?foo[]=array&foo[hash]=hash
EDIT:
Also, it is possible to implement middleware which checks for correctness of parameters.
Catching bad queries by middleware
# config/application.rb
require File.expand_path('../../lib/query_validator', __FILE__)
module MyApp
class Application < Rails::Application
# configurations
config.middleware.insert_before('ActionDispatch::ShowExceptions', QueryValidator)
end
end
# lib/query_validator.rb
class QueryValidator
def initialize(app)
@app = app
end
def call(env)
begin
Rack::Utils.parse_nested_query(env['QUERY_STRING'])
env['QUERY_STRING'].valid_encoding? or
raise ActionController::BadRequest, "Invalid parameter: #{env['QUERY_STRING']}"
rescue => e
env['QUERY_STRING'] = ''
env['my_app.query_errors'] = 'Invalid query.'
end
@app.call(env)
end
end
# application_controller.rb
class ApplicationController < ActionController::Base
before_filter do
if env['my_app.query_errors']
flash[:alert] = env['my_app.query_errors']
redirect_to root_path
end
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With