lib/rack-request-object-logger.rb
# frozen_string_literal: true
require 'rack'
require 'securerandom'
class RackRequestObjectLogger
def initialize(app, request_model)
@app = app
@model = request_model
end
def call(env)
start_time = Time.now.utc
app_result = @app.call(env)
end_time = Time.now.utc
logger_object = @model.new
logger_object.application_server_request_start = start_time
logger_object.application_server_request_end = end_time
request = Rack::Request.new(env)
logger_object.data = request.env.select do |header, value|
# don't bother with values other than a string
next if !value.is_a?(String)
# https://tools.ietf.org/html/rfc3875 CGI 1.1 spec
# reject cookies
next if ['HTTP_COOKIE'].include?(header)
# 1. predefined
# 2. $scheme - rack is for HTTP, won't handle other protocols here
# 3. http headers
# 4. REQUEST_URI seems to be defined like everywhere (PHP, Python, Rack), but is not a part of CGI spec
# ORIGINAL_FULLPATH and ORIGINAL_SCRIPT_NAME is Rack specific
[
'AUTH_TYPE', 'CONTENT_LENGTH', 'CONTENT_TYPE', 'GATEWAY_INTERFACE', 'PATH_INFO',
'PATH_TRANSLATED', 'QUERY_STRING', 'REMOTE_ADDR', 'REMOTE_HOST', 'REMOTE_IDENT',
'REMOTE_USER', 'REQUEST_METHOD', 'SCRIPT_NAME', 'SERVER_NAME', 'SERVER_PORT',
'SERVER_PROTOCOL', 'SERVER_SOFTWARE'
].include?(header) || ['HTTP', 'HTTPS'].include?(header) || header =~ /\AHTTP_\w+\z/ ||
['REQUEST_URI', 'ORIGINAL_FULLPATH', 'ORIGINAL_SCRIPT_NAME'].include?(header)
end
logger_object.uid = request.env['action_dispatch.request_id'] || SecureRandom.uuid
logger_object.status_code = app_result.first
logger_object.save
app_result
end
end