lib/raven/integrations/rack.rb in sentry-raven-0.15.2 vs lib/raven/integrations/rack.rb in sentry-raven-0.15.3

- old
+ new

@@ -19,11 +19,10 @@ # run lambda { |env| raise "Rack down" } # end # # Use a standard Raven.configure call to configure your server credentials. class Rack - def self.capture_type(exception, env, options = {}) if env['raven.requested_at'] options[:time_spent] = Time.now - env['raven.requested_at'] end Raven.capture_type(exception, options) do |evt| @@ -58,13 +57,70 @@ Raven.logger.debug "Collecting %p: %s" % [ e.class, e.message ] Raven::Rack.capture_exception(e, env) raise end - error = env['rack.exception'] || env['sinatra.error'] || env['action_dispatch.exception'] - + error = env['rack.exception'] || env['sinatra.error'] Raven::Rack.capture_exception(error, env) if error response end + end + + module RackInterface + def from_rack(env_hash) + req = ::Rack::Request.new(env_hash) + + self.url = req.scheme && req.url.split('?').first + self.method = req.request_method + self.query_string = req.query_string + self.data = read_data_from(req) + + self.headers = format_headers_for_sentry(env_hash) + self.env = format_env_for_sentry(env_hash) + end + + private + + def read_data_from(request) + if request.form_data? + request.POST + elsif request.body + data = request.body.read + request.body.rewind + data + end + end + + def format_headers_for_sentry(env_hash) + env_hash.each_with_object({}) do |(key, value), memo| + key = key.to_s # rack env can contain symbols + value = value.to_s + next unless key.upcase == key # Non-upper case stuff isn't either + # Rack adds in an incorrect HTTP_VERSION key, which causes downstream + # to think this is a Version header. Instead, this is mapped to + # env['SERVER_PROTOCOL']. But we don't want to ignore a valid header + # if the request has legitimately sent a Version header themselves. + # See: https://github.com/rack/rack/blob/028438f/lib/rack/handler/cgi.rb#L29 + next if key == 'HTTP_VERSION' && value == ENV['SERVER_PROTOCOL'] + if key.start_with?('HTTP_') + # Header + http_key = key[5..key.length - 1].split('_').map(&:capitalize).join('-') + memo[http_key] = value + elsif %w(CONTENT_TYPE CONTENT_LENGTH).include? key + memo[key.capitalize] = value + end + end + end + + def format_env_for_sentry(env_hash) + trimmed_hash = env_hash.select do |k, _v| + %w(REMOTE_ADDR SERVER_NAME SERVER_PORT).include? k.to_s + end + Hash[trimmed_hash] # select returns an Array in Ruby 1.8 + end + end + + class HttpInterface + include RackInterface end end