application controller: fix bad file extension errors.

Fix requests with bad file extensions not always returning errors correctly:

* https://danbooru.donmai.us/posts.jpg
* https://danbooru.donmai.us/posts.blah
* https://danbooru.donmai.us/posts/bad.jpg
* https://danbooru.donmai.us/posts/bad.blah
This commit is contained in:
evazion
2019-08-08 22:16:39 -05:00
parent 8d706f4fd7
commit 35dfc704bc
3 changed files with 62 additions and 42 deletions

View File

@@ -18,8 +18,6 @@ class ApplicationController < ActionController::Base
rescue_from Exception, :with => :rescue_exception
rescue_from User::PrivilegeError, :with => :access_denied
rescue_from SessionLoader::AuthenticationFailure, :with => :authentication_failed
rescue_from Danbooru::Paginator::PaginationError, :with => :render_pagination_limit
rescue_from PG::ConnectionBad, with: :bad_db_connection
rescue_from ActionController::UnpermittedParameters, :with => :access_denied
# This is raised on requests to `/blah.js`. Rails has already rendered StaticController#not_found
@@ -36,18 +34,6 @@ class ApplicationController < ActionController::Base
response.headers["Access-Control-Allow-Origin"] = "*"
end
def bad_db_connection
respond_to do |format|
format.json do
render json: {success: false, reason: "database is unavailable"}.to_json, status: 503
end
format.html do
render template: "static/service_unavailable", status: 503
end
end
end
def track_only_param
if params[:only]
RequestStore[:only_param] = params[:only].split(/,/)
@@ -89,39 +75,37 @@ class ApplicationController < ActionController::Base
def rescue_exception(exception)
@exception = exception
if Rails.env.test? && ENV["DEBUG"]
puts "---"
STDERR.puts("#{exception.class} exception thrown: #{exception.message}")
exception.backtrace.each {|x| STDERR.puts(x)}
puts "---"
end
if exception.is_a?(::ActiveRecord::StatementInvalid) && exception.to_s =~ /statement timeout/
case exception
when ActiveRecord::QueryCanceled
if Rails.env.production?
NewRelic::Agent.notice_error(exception, :uri => request.original_url, :referer => request.referer, :request_params => params, :custom_params => {:user_id => CurrentUser.user.id, :user_ip_addr => CurrentUser.ip_addr})
end
@error_message = "The database timed out running your query."
render :template => "static/error", :status => 500
elsif exception.is_a?(::ActiveRecord::RecordNotFound)
@error_message = "That record was not found"
render :template => "static/error", :status => 404
elsif exception.is_a?(NotImplementedError)
flash[:notice] = "This feature isn't available: #{@exception.message}"
respond_to do |fmt|
fmt.html { redirect_back fallback_location: root_path }
fmt.js { head 501 }
fmt.json { render template: "static/error", status: 501 }
fmt.xml { render template: "static/error", status: 501 }
end
render_error_page(500, "The database timed out running your query.")
when ActiveRecord::RecordNotFound
render_error_page(404, "That record was not found")
when ActionController::UnknownFormat
@error_message = "#{request.format.to_s} is not a supported format for this page."
render "static/error.html", status: 406
when Danbooru::Paginator::PaginationError
render_error_page(410, @exception.message)
when NotImplementedError
render_error_page(501, "This feature isn't available: #{@exception.message}")
when PG::ConnectionBad
render_error_page(503, "The database is unavailable. Try again later.")
else
render template: "static/error", status: 500
render_error_page(500, @exception.message)
end
end
def render_pagination_limit
@error_message = "You can only view up to #{Danbooru.config.max_numbered_pages} pages. Please narrow your search terms."
render :template => "static/error", :status => 410
def render_error_page(status, message)
@error_message = message
if request.format.symbol.in?(%i[html json xml js atom])
render template: "static/error", status: status
else
render template: "static/error.html", status: status
end
end
def authentication_failed

View File

@@ -1,3 +0,0 @@
<h1>Service Unavailable</h1>
<p>Try again later</p>

View File

@@ -0,0 +1,39 @@
require "test_helper"
class ApplicationControllerTest < ActionDispatch::IntegrationTest
context "The application controller" do
should "return 406 Not Acceptable for a bad file extension" do
get posts_path, params: { format: :jpg }
assert_response 406
get posts_path, params: { format: :blah }
assert_response 406
end
context "on a RecordNotFound error" do
should "return 404 Not Found even with a bad file extension" do
get post_path("bad.json")
assert_response 404
get post_path("bad.jpg")
assert_response 404
get post_path("bad.blah")
assert_response 404
end
end
context "on a PaginationError" do
should "return 410 Gone even with a bad file extension" do
get posts_path, params: { page: 999999999 }, as: :json
assert_response 410
get posts_path, params: { page: 999999999 }, as: :jpg
assert_response 410
get posts_path, params: { page: 999999999 }, as: :blah
assert_response 410
end
end
end
end