diff --git a/lib/raven/integrations/rack.rb b/lib/raven/integrations/rack.rb index f1115f323..f6a411f33 100644 --- a/lib/raven/integrations/rack.rb +++ b/lib/raven/integrations/rack.rb @@ -66,4 +66,62 @@ def call(env) 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 diff --git a/lib/raven/interfaces/http.rb b/lib/raven/interfaces/http.rb index 46ac5c599..ad89d2d18 100644 --- a/lib/raven/interfaces/http.rb +++ b/lib/raven/interfaces/http.rb @@ -17,43 +17,6 @@ def initialize(*arguments) self.cookies = nil super(*arguments) end - - def from_rack(env) - req = ::Rack::Request.new(env) - self.url = req.scheme && req.url.split('?').first - self.method = req.request_method - self.query_string = req.query_string - server_protocol = env['SERVER_PROTOCOL'] - env.each_pair do |key, value| - key = key.to_s #rack env can contain symbols - 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' and value == server_protocol - if key.start_with?('HTTP_') - # Header - http_key = key[5..key.length - 1].split('_').map(&:capitalize).join('-') - self.headers[http_key] = value.to_s - elsif %w(CONTENT_TYPE CONTENT_LENGTH).include? key - self.headers[key.capitalize] = value.to_s - elsif %w(REMOTE_ADDR SERVER_NAME SERVER_PORT).include? key - # Environment - self.env[key] = value.to_s - end - end - - self.data = - if req.form_data? - req.POST - elsif req.body - data = req.body.read - req.body.rewind - data - end - end end register_interface :http => HttpInterface