require 'uri' module Hawkei module Plugins module Rack ## # Hawkei \Plugins \Rack \Middleware # # Middleware for Rack # class Middleware def initialize(app) @app = app end def call(env) request = ::Rack::Request.new(env) store_tracker(request) store_request_data(request, env) Hawkei::Plugins::Rails::MiddlewareData.store_data(request) if defined?(::Rails) status, headers, body = @app.call(env) write_cookie_session_tracker_id!(headers) [status, headers, body] ensure Hawkei::Store.clear! unless env['hawkei_test'] end private def session_tracker_id_name '_hawkei_stid'.freeze end def store_tracker(request) Hawkei::Store.set( :session_tracker_id, request.cookies[session_tracker_id_name] || SecureRandom.uuid ) end def store_request_data(request, env) Hawkei::Store.set( :request, url: obfuscate_uri(request.url), ssl: request.ssl?, host: request.host, port: request.port, path: request.path, referrer: obfuscate_uri(request.referrer), method: request.request_method, xhr: request.xhr?, user_agent: request.user_agent, ip: request.ip, get_params: obfuscation_get_params(request, 'GET'), post_params: obfuscation_get_params(request, 'POST'), headers: obfuscate_headers(env) ) Hawkei::Store.bulk_set( server_software: request.env['SERVER_SOFTWARE'] ) end def write_cookie_session_tracker_id!(headers) ::Rack::Utils.set_cookie_header!( headers || {}, session_tracker_id_name, Util.deep_compact( value: Hawkei::Store.get(:session_tracker_id), path: '/', domain: Hawkei.configurations.domain, http_only: false, max_age: (10 * 365 * 24 * 60 * 60), ) ) end def obfuscate_uri(url) uri = URI.parse(url) params = Util.deep_obfuscate_value( ::Rack::Utils.parse_query(uri.query), Hawkei.configurations.obfuscated_fields, 'HIDDEN' ) return url if params.empty? uri.merge( "?#{::Rack::Utils.build_query(params)}" ).to_s rescue StandardError => _e '' end def obfuscation_get_params(request, type) Util.deep_obfuscate_value( request.send(type), Hawkei.configurations.obfuscated_fields ) rescue StandardError => _e {} end def https_request?(env) env['HTTPS'] == 'on' || env['HTTP_X_FORWARDED_SSL'] == 'on' || env['HTTP_X_FORWARDED_PROTO'].to_s.split(',').first == 'https' || env['rack.url_scheme'] == 'https' end def obfuscate_headers(env) skip_headers = %w[HTTP_COOKIE] headers = env.keys.grep(/^HTTP_|^CONTENT_/).each_with_object({}) do |key, hash| next if skip_headers.include?(key) name = key.gsub(/^HTTP_/, '').split('_').map(&:capitalize).join('-') hash[name] = env[key] end Util.deep_obfuscate_value( headers, Hawkei.configurations.obfuscated_fields ) rescue StandardError => _e {} end end end end end