如何为 Rails/Puma 的 404 未找到页面设置 HTTP headers

How to set HTTP headers for 404 Not found pages with Rails/Puma

我需要在我的 rails 应用程序中为 return 404 - Not Found 的页面设置 X-Frame-Options HTTP header,但我不知道如何设置去做吧。我无法使用 rails 设置这些 header,我发现了一个可能的原因 here。但是,我也不知道如何使用 Web 服务器设置它们,我使用的是 Puma。

我的 404 - not found 页面中实际上没有任何可以 ClickJacked 的内容,但外部安全组织仍然要求我这样做。

在 Rails 中,异常由 config.exceptions_app 处理。默认应用程序仅呈现 public 目录中的静态 html 文件,但这可以是任何机架兼容的应用程序。

Rack 兼容应用程序的最基本示例是:

app = ->(env){  [ 404, { "Content-Type" => "text/plain", "X-Frame-Options" => "some value" }, ["Oh no I cant find it!"] ] }

它接受一个参数(一个散列)和returns一个数组(状态,headers,body)。

Rails 路由和 ActionController::Metal(以及您所有的控制器)都是机架兼容的应用程序,甚至 config/application.rb。其实Rails只是Rack apps的俄罗斯套娃方案

如果你想通过路由处理这个问题,你可以这样做:

# config/application.rb
config.exceptions_app = self.routes
# config/routes.rb
get '/404', to: "errors#not_found"
get '/422', to: "errors#unprocessable_entity"
get '/500', to: "errors#internal_error"
class ErrorsController < ActionController::Base
  before_action do
    response.set_header('X-Frame-Options', 'HEADER VALUE')
  end

  def not_found
    respond_to do |format|
      format.html { render file: Rails.root.join('public', '404.html'), layout: false, status: :not_found }
    end
  end

  def unprocessable_entity 
    respond_to do |format|
      format.html { render file: Rails.root.join('public', '422.html'), layout: false, status: :unprocessable_entity }
    end
  end

  def internal_error
    respond_to do |format|
      format.html { render file: Rails.root.join('public', '500.html'), layout: false, status: :internal_server_error }
    end
  end
end