class Rack::Contrib::StaleCall

Validate a request’s age isn’t too old or too young, indicating a replayed request.

Constants

VERSION

Attributes

opts[R]

Public Class Methods

new(app, opts = {}) click to toggle source
# File lib/rack/contrib/stale_call.rb, line 16
def initialize app, opts = {}
  @app = app
  @opts = opts
  @opts[:header] ||= 'Date'
  @opts[:grace] ||= 5
  @opts[:logger] ||= Logger.new('/dev/null')
end

Public Instance Methods

call(env) click to toggle source

Verify the age of the request

# File lib/rack/contrib/stale_call.rb, line 50
def call env
  unless env.has_key? header_variable
    @opts[:logger].info "Denied: #{opts[:header]} header missing."
    return date_error
  end

  diff_seconds = date_to_diff_seconds(env[header_variable])
  unless date_is_recent diff_seconds
    @opts[:logger].info sprintf(
      "Denied: %s header is %ss over the %ss grace period.",
      @opts[:header],
      diff_seconds - @opts[:grace],
      @opts[:grace]
    )
    return date_error
  end

  @app.call env
end
date_error() click to toggle source

Return the standard date error contents

# File lib/rack/contrib/stale_call.rb, line 30
def date_error
  [401, {}, []]
end
date_is_recent(seconds) click to toggle source

Determine if the date is recent enough

# File lib/rack/contrib/stale_call.rb, line 45
def date_is_recent seconds
  seconds <= opts[:grace]
end
date_to_diff_seconds(date) click to toggle source

Convert an RFC2822 compatible date string to a diff against now

# File lib/rack/contrib/stale_call.rb, line 35
def date_to_diff_seconds date
  date = DateTime.rfc2822(date)
  datediff = date - DateTime.now # Number of days apart as a float
  datediff *= 24 # hours apart
  datediff *= 60 # minutes apart
  datediff *= 60 # seconds apart
  seconds = datediff.to_i.abs
end
header_variable() click to toggle source

Translate a header name to a variable which Rack might provide

# File lib/rack/contrib/stale_call.rb, line 25
def header_variable
  'HTTP_' + opts[:header].upcase.gsub(/-/, '_')
end