starmammoth/rack-request-object-logger

View on GitHub
lib/rack-request-object-logger.rb

Summary

Maintainability
A
45 mins
Test Coverage
# 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