Class: Landline::Cookie

Inherits:
Object
  • Object
show all
Defined in:
lib/landline/util/cookie.rb

Overview

Utility class for handling cookies

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, value, params = {}) ⇒ Cookie

Returns a new instance of Cookie.

Parameters:

  • key (String)

    cookie name

  • value (String)

    cookie value

  • params (Hash) (defaults to: {})

    cookie parameters

Options Hash (params):

  • "domain" (String)
  • "path" (String)
  • "secure" (boolean, nil) — default: false
  • "httponly" (boolean, nil) — default: false
  • "samesite" (String)
  • "max-age" (String, Integer)
  • "expires" (String, Date)

Raises:

  • Landline::ParsingError invalid cookie parameters



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/landline/util/cookie.rb', line 31

def initialize(key, value, params = {})
  unless key.match?(/\A#{HeaderRegexp::COOKIE_NAME}\z/o)
    raise Landline::ParsingError, "invalid cookie key: #{key}"
  end

  unless value.match?(/\A#{HeaderRegexp::COOKIE_VALUE}\z/o)
    raise Landline::ParsingError, "invalid cookie value: #{value}"
  end

  # Make param keys strings
  params.transform_keys!(&:to_s)

  # Primary cookie parameters
  @key = key
  @value = value
  setup_params(params)

  # Cookie signing parameters
  setup_hmac(params)
end

Instance Attribute Details

#domainObject (readonly)

Returns the value of attribute domain.



98
99
100
# File 'lib/landline/util/cookie.rb', line 98

def domain
  @domain
end

#expiresObject (readonly)

Returns the value of attribute expires.



98
99
100
# File 'lib/landline/util/cookie.rb', line 98

def expires
  @expires
end

#httponlyObject (readonly)

Returns the value of attribute httponly.



98
99
100
# File 'lib/landline/util/cookie.rb', line 98

def httponly
  @httponly
end

#keyObject

Returns the value of attribute key.



97
98
99
# File 'lib/landline/util/cookie.rb', line 97

def key
  @key
end

#maxageObject (readonly)

Returns the value of attribute maxage.



98
99
100
# File 'lib/landline/util/cookie.rb', line 98

def maxage
  @maxage
end

#pathObject (readonly)

Returns the value of attribute path.



98
99
100
# File 'lib/landline/util/cookie.rb', line 98

def path
  @path
end

#samesiteObject (readonly)

Returns the value of attribute samesite.



98
99
100
# File 'lib/landline/util/cookie.rb', line 98

def samesite
  @samesite
end

#secureObject (readonly)

Returns the value of attribute secure.



98
99
100
# File 'lib/landline/util/cookie.rb', line 98

def secure
  @secure
end

#valueObject

Returns the value of attribute value.



97
98
99
# File 'lib/landline/util/cookie.rb', line 97

def value
  @value
end

Class Method Details

Create cookie(s) from a “Cookie: ” format

Parameters:

  • data (String)

    value part of “Cookie: ” header

Returns:



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/landline/util/cookie.rb', line 112

def self.from_cookie_string(data)
  hash = {}
  return hash if data.nil?

  data.split(";").map do |cookiestr|
    key, value = cookiestr.match(/([^=]+)=?(.*)/).to_a[1..].map(&:strip)
    next unless key and value

    cookie = Cookie.new(key, value)
    if hash[cookie.key]
      hash[cookie.key].append(cookie)
    else
      hash[cookie.key] = [cookie]
    end
  end
  hash
end

.from_setcookie_string(data) ⇒ Cookie

Create cookie from a “Set-Cookie: ” format

Parameters:

  • data (String)

    value part of “Set-Cookie: ” header

Returns:



103
104
105
106
107
# File 'lib/landline/util/cookie.rb', line 103

def self.from_setcookie_string(data)
  kvpair, params = parse_value(data, regexp: HeaderRegexp::COOKIE_PARAM)
  key, value = kvpair.match(/([^=]+)=?(.*)/).to_a[1..].map(&:strip)
  Cookie.new(key, value, params)
end

Instance Method Details

#finalizeString

Convert cookie to “Set-Cookie: ” string representation.

Returns:

  • (String)


54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/landline/util/cookie.rb', line 54

def finalize
  sign(@hmac, algorithm: @algorithm, sep: @sep) if @hmac
  ParserCommon.make_value(
    "#{key.to_s.strip}=#{value.to_s.strip}",
    {
      "Domain" => @domain,
      "Path" => @path,
      "Expires" => @expires,
      "Max-Age" => @maxage,
      "SameSite" => @samesite,
      "Secure" => @secure,
      "HttpOnly" => @httponly
    }
  )
end

#finalize_shortString

Convert cookie to “Cookie: ” string representation (no params)

Returns:

  • (String)


72
73
74
75
# File 'lib/landline/util/cookie.rb', line 72

def finalize_short
  sign(@hmac, algorithm: @algorithm, sep: @sep) if @hmac
  "#{key.to_s.strip}=#{value.to_s.strip}"
end

#sign(key, algorithm: "sha256", sep: "&") ⇒ Object

Sign the cookie value with HMAC

Parameters:

  • key (String)

    HMAC signing key

  • algorithm (String) (defaults to: "sha256")

    Hash algorithm to use

  • sep (String) (defaults to: "&")

    Hash separator



81
82
83
# File 'lib/landline/util/cookie.rb', line 81

def sign(key, algorithm: "sha256", sep: "&")
  @value += sep + ::OpenSSL::HMAC.base64digest(algorithm, key, @value)
end

#verify(key, algorithm: "sha256", sep: "&") ⇒ Boolean

Verify HMAC signature

Parameters:

  • key (String)

    HMAC signing key

  • algorithm (String) (defaults to: "sha256")

    Hash algorithm

  • sep (String) (defaults to: "&")

    Hash separator

Returns:

  • (Boolean)

    whether value is signed and valid



90
91
92
93
94
95
# File 'lib/landline/util/cookie.rb', line 90

def verify(key, algorithm: "sha256", sep: "&")
  val, sig = @value.match(/\A(.*)#{sep}([A-Za-z0-9+\/=]+)\z/).to_a[1..]
  return false unless val and sig

  sig == ::OpenSSL::HMAC.base64digest(algorithm, key, val)
end