require 'set' module Honeybadger module Util # Constructs a request hash from a Rack::Request matching the /v1/notices # API specification. module RequestHash HTTP_HEADER_PREFIX = 'HTTP_'.freeze CGI_WHITELIST = %w( AUTH_TYPE CONTENT_LENGTH CONTENT_TYPE GATEWAY_INTERFACE HTTPS REMOTE_ADDR REMOTE_HOST REMOTE_IDENT REMOTE_USER REQUEST_METHOD SERVER_NAME SERVER_PORT SERVER_PROTOCOL SERVER_SOFTWARE ).freeze def self.from_env(env) return {} unless defined?(::Rack::Request) return {} unless env hash, request = {}, ::Rack::Request.new(env.dup) hash[:url] = extract_url(request) hash[:params] = extract_params(request) hash[:component] = hash[:params]['controller'] hash[:action] = hash[:params]['action'] hash[:session] = extract_session(request) hash[:cgi_data] = extract_cgi_data(request) hash end def self.extract_url(request) request.env['honeybadger.request.url'] || request.url rescue => e "Failed to access URL -- #{e}" end def self.extract_params(request) (request.env['action_dispatch.request.parameters'] || request.params).to_hash || {} rescue => e { error: "Failed to access params -- #{e}" } end def self.extract_session(request) request.session.to_hash rescue => e # Rails raises ArgumentError when `config.secret_token` is missing, and # ActionDispatch::Session::SessionRestoreError when the session can't be # restored. { error: "Failed to access session data -- #{e}" } end def self.extract_cgi_data(request) request.env.each_with_object({}) do |(k,v), env| next unless k.is_a?(String) next unless k.start_with?(HTTP_HEADER_PREFIX) || CGI_WHITELIST.include?(k) env[k] = v end end end end end