module AuthorizationHeaderParser

Constants

ANYTHING_BUT_EQ
COMMA
EQ
ESCAPED_QUOTE
NON_WHITESPACE
QUOTE
UNTIL_BACKSLASH_OR_QUOTE
VERSION
WHITESPACE

Public Instance Methods

parse(value) click to toggle source

Parse a custom scheme + params Authorization header.

parse('absurd-auth token="12345"') #=> ['absurd-auth', {'token' => '12345'}]
# File lib/authorization_header_parser.rb, line 22
def parse(value)
  scanner = StringScanner.new(value)
  scheme = scanner.scan(NON_WHITESPACE)
  raise InvalidHeader, "Scheme not provided" unless scheme
  scanner.skip(WHITESPACE)

  [scheme.strip, extract_params_from_scanner(scanner)]
end
parse_params(string) click to toggle source

Parse Authorization params. Most useful in combination with Rack::Auth::AbstractRequest

For instance, with 'Authorization: absurd-auth token=“12345”':

auth = Rack::Auth::AbstractRequest.new(env)
params = parse(auth.params) #=> {'token' => '12345}
# File lib/authorization_header_parser.rb, line 37
def parse_params(string)
  extract_params_from_scanner(StringScanner.new(string))
end

Private Instance Methods

extract_params_from_scanner(scanner) click to toggle source

codereview.stackexchange.com/questions/41270 stackoverflow.com/questions/134936

# File lib/authorization_header_parser.rb, line 56
def extract_params_from_scanner(scanner)
  params = {}
  until scanner.eos?
    key = scanner.scan(ANYTHING_BUT_EQ)
    raise ParseError.new("Expected =, but found none", scanner) unless scanner.skip(EQ)

    if scanner.eos? # Last parameter was empty, return
      params[key] = ''
      return params
    end

    if scanner.skip(QUOTE) # Quoted value
      buf = ''
      until scanner.eos?
        if scanner.scan(UNTIL_BACKSLASH_OR_QUOTE)
          buf << scanner.matched
        elsif scanner.scan(ESCAPED_QUOTE)
          buf << '"'
        elsif scanner.scan(QUOTE)
          params[key] = buf
          break
        end
      end
    elsif bare_value = scanner.scan(/[^,"]+/) # Bare parameter
      params[key] = bare_value
    else # Empty parameter
      params[key] = ''
    end
    scanner.skip(WHITESPACE)
    if !scanner.eos? && !scanner.skip(COMMA)
      raise ParseError.new("Expected end of header or a comma", scanner)
    end
    scanner.skip(WHITESPACE)
  end
  params
end