Class: Rage::Cookies

Inherits:
Object
  • Object
show all
Defined in:
lib/rage/cookies.rb

Overview

Cookies provide a convenient way to store small amounts of data on the client side that persists across requests. They are commonly used for session management, personalization, and tracking user preferences.

Rage cookies support simple, signed, and encrypted cookies.

To use cookies, add the domain_name gem to your Gemfile:

bundle add domain_name

Additionally, if you need to use signed or encrypted cookies, see Session for setup steps.

Usage

Basic Cookies

Read and write simple string values:

# Set a cookie
cookies[:user_name] = "Alice"

# Read a cookie
cookies[:user_name] # => "Alice"

# Delete a cookie
cookies.delete(:user_name)

Set cookies with additional options for security and control:

cookies[:user_id] = {
  value: "12345",
  expires: 1.year.from_now,
  secure: true,
  httponly: true,
  same_site: :lax
}

Encrypted Cookies

Store sensitive data securely with automatic encryption:

# Set an encrypted cookie
cookies.encrypted[:api_token] = "secret-token"

# Read an encrypted cookie
cookies.encrypted[:api_token] # => "secret-token"

Signed Cookies

Store readable values with tamper protection:

# Set a signed cookie
cookies.signed[:user_id] = 123

# Read a signed cookie
cookies.signed[:user_id] # => "123"

Permanent Cookies

Create cookies that expire 20 years from now:

cookies.permanent[:remember_token] = "token-value"

# Can be combined with encrypted
cookies.permanent.encrypted[:user_id] = current_user.id

Domain Configuration

Control which domains can access your cookies:

# Specific domain
cookies[:cross_domain] = { value: "data", domain: "example.com" }

# All subdomains
cookies[:shared] = { value: "data", domain: :all }

# Multiple allowed domains
cookies[:limited] = { value: "data", domain: ["app.example.com", "api.example.com"] }

See Also:

Defined Under Namespace

Modules: RbNaClKeyBuilder Classes: EncryptedJar, SignedJar, SimpleJar

Instance Method Summary collapse

Instance Method Details

#[](key) ⇒ String

Read a cookie.

Parameters:

  • key (Symbol)

Returns:

  • (String)


138
139
140
141
# File 'lib/rage/cookies.rb', line 138

def [](key)
  value = request_cookies[key]
  @jar.load(value) if value
end

#[]=(key, value) ⇒ Object

Set a cookie.

Examples:

cookie[:user_id] = current_user.id
cookie[:user_id] = { value: current_user.id, httponly: true, secure: true }

Parameters:

  • key (Symbol)
  • value (String, Hash)

Options Hash (value):

  • :path (String)
  • :secure (Boolean)
  • :httponly (Boolean)
  • :same_site (nil, :none, :lax, :strict)
  • :expires (Time)
  • :domain (String, Array<String>, :all)
  • :value (String)


205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/rage/cookies.rb', line 205

def []=(key, value)
  unless value.is_a?(Hash)
    serialized_value = @jar.dump(value)
    @request_cookies[key] = serialized_value
    Rack::Utils.set_cookie_header!(@headers, key, { value: serialized_value, expires: @expires })
    return
  end

  if (domain = value[:domain])
    host = Rack::Request.new(@env).host

    processed_domain = if domain.is_a?(String)
      domain
    elsif domain == :all
      DomainName(host).domain
    elsif domain.is_a?(Array)
      domain.find { |candidate| candidate.casecmp?(host) } if host
    end
  end

  serialized_value = @jar.dump(value[:value])
  Rack::Utils.set_cookie_header!(@headers, key, {
    **value,
    value: serialized_value,
    domain: processed_domain,
    expires: value[:expires] || @expires
  })
  @request_cookies[key] = serialized_value
end

#delete(key, path: "/", domain: nil) ⇒ Object

Delete a cookie.

Parameters:

  • key (Symbol)
  • path (String) (defaults to: "/")
  • domain (String) (defaults to: nil)


155
156
157
158
# File 'lib/rage/cookies.rb', line 155

def delete(key, path: "/", domain: nil)
  @request_cookies[key] = nil
  Rack::Utils.delete_cookie_header!(@headers, key, { path: path, domain: domain })
end

#encrypted ⇒ Object

Returns a jar that'll automatically encrypt cookie values before sending them to the client and will decrypt them for read. If the cookie was tampered with by the user (or a 3rd party), nil will be returned.

This jar requires that you set a suitable secret for the verification on your app's secret_key_base.

Examples:

cookies.encrypted[:user_id] = current_user.id


167
168
169
# File 'lib/rage/cookies.rb', line 167

def encrypted
  dup.tap { |c| c.jar = EncryptedJar }
end

#inspect ⇒ Object



235
236
237
238
239
240
241
242
243
244
# File 'lib/rage/cookies.rb', line 235

def inspect
  cookies = request_cookies.transform_values do |v|
    decoded = Base64.urlsafe_decode64(v) rescue nil
    is_encrypted = decoded&.start_with?(EncryptedJar::PADDING)

    is_encrypted ? "<encrypted>" : v
  end

  "#<#{self.class.name} @request_cookies=#{cookies.inspect}"
end

#permanent ⇒ Object

Returns a jar that'll automatically set the assigned cookies to have an expiration date 20 years from now.

Examples:

cookies.permanent[:user_id] = current_user.id


186
187
188
# File 'lib/rage/cookies.rb', line 186

def permanent
  dup.tap { |c| c.expires = Date.today.next_year(20) }
end

#signed ⇒ Object

Returns a jar that'll automatically sign cookie values before sending them to the client and verify them for read. If the cookie was tampered with by the user (or a 3rd party), nil will be returned.

This jar requires that you set a suitable secret for the verification on your app's secret_key_base.

Examples:

cookies.signed[:user_id] = current_user.id


178
179
180
# File 'lib/rage/cookies.rb', line 178

def signed
  dup.tap { |c| c.jar = SignedJar }
end

#size ⇒ Integer

Get the number of cookies.

Returns:

  • (Integer)


146
147
148
# File 'lib/rage/cookies.rb', line 146

def size
  request_cookies.count { |_, v| !v.nil? }
end