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



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/landline/util/cookie.rb', line 24

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

  unless value.match? HeaderRegexp::COOKIE_VALUE
    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.



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

def domain
  @domain
end

#expiresObject (readonly)

Returns the value of attribute expires.



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

def expires
  @expires
end

#httponlyObject (readonly)

Returns the value of attribute httponly.



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

def httponly
  @httponly
end

#keyObject

Returns the value of attribute key.



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

def key
  @key
end

#maxageObject (readonly)

Returns the value of attribute maxage.



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

def maxage
  @maxage
end

#pathObject (readonly)

Returns the value of attribute path.



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

def path
  @path
end

#samesiteObject (readonly)

Returns the value of attribute samesite.



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

def samesite
  @samesite
end

#secureObject (readonly)

Returns the value of attribute secure.



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

def secure
  @secure
end

#valueObject

Returns the value of attribute value.



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

def value
  @value
end

Class Method Details

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

Parameters:

  • data (String)

    value part of “Cookie: ” header

Returns:



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/landline/util/cookie.rb', line 105

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)
    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:



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

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)


47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/landline/util/cookie.rb', line 47

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)


65
66
67
68
# File 'lib/landline/util/cookie.rb', line 65

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



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

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



83
84
85
86
87
88
# File 'lib/landline/util/cookie.rb', line 83

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