Lucky Logo

# Cookies and Sessions

You can set and access cookies/session values in Lucky like this:

class FooAction < BrowserAction
  get "/foo" do
    cookies.set("name", "Sally")
    cookies["name"] = "Sally"

    cookies.get("name") # Will return "Sally"
    cookies["name"] # or use shorthand

    cookies.get?("person") # Will return nil
    cookies["person"]?

    # You can use Symbol for your key as well
    session.set(:name, "Sally")
    session.get(:name) # Will return "Sally"
    session.get("person") # oops! An exception is raised because this key doesn't exist
    plain_text "Cookies!"
  end
end

Cookies are encrypted by Lucky by default when you use set or []=. If you need to set a raw value unencrypted, Lucky gives you that option:

cookies.set_raw("name", "Sally") # Sets a raw unencrypted cookie
cookies.get_raw("name") # Will return "Sally"
cookies.get_raw?("person") # Will return nil

# Clearing Sessions and Cookies

If you need to remove a session, or delete a cookie, do this:

# Delete a specific session key
session.delete(:name)

# Clear the current session
session.clear

# Delete a specific cookie
cookies.delete("name")
cookies.deleted?("person") #=> false

# Delete all cookies
cookies.clear

Cookies that have been set with a specific path or domain cannot be deleted unless you pass in the original values. To clear these out, you can pass a block to the delete() method. See RFC-2109.

cookies.delete(:remember_me) do |cookie|
  cookie.domain("mysite.co")
  cookie.path(Home::Index.path)
end

# Configuring Cookies

If you need to customize specific cookie options, each cookie is an instance of HTTP::Cookie, which gives you access to several helpful methods.

# This gives you a HTTP::Cookie or raise an exception
c_is_for_cookie = cookies.get_raw("cookiedough")

# Set the name of the cookie to "cookie-dough"
c_is_for_cookie.name("cookie-dough")

# Set the value of cookie-dough to "yum"
c_is_for_cookie.value("yum")

# Set the path for the cookie to "/baking"
c_is_for_cookie.path("/baking")

# Set the expires date to tomorrow
c_is_for_cookie.expires(1.day.from_now)

# Set the domain to cookie.monst.er
c_is_for_cookie.domain("cookie.monst.er")

# Make the cookie secure
c_is_for_cookie.secure(true)

# Set the cookie to HTTP only
c_is_for_cookie.http_only(true)

# Set the cookie SameSite to Lax.
# You can also use `:strict` here.
c_is_for_cookie.samesite(:lax)

The Lucky::CookieJar configuration is located in your app’s config/cookies.cr file. You can set defaults for your cookies when they’re written.

# config/cookies.cr
Lucky::CookieJar.configure do |settings|
  settings.on_set = ->(cookie : HTTP::Cookie) {
    cookie
      .secure(true)
      .http_only(true)
      .samesite(:strict)
      .expires(1.year.from_now)
      .domain("mydomain.com")
  }
end

# Disabling Cookies

There may be an action where you need disable writing cookies. For this, you can use the disable_cookies macro in the action you want to skip writing cookies.

class Api::Posts::Index < ApiAction
  disable_cookies

  get "/posts" do
    json([] of Post)
  end
end

You will also need to disable cookies for your errors to avoid sending this data when an error is raised in your API.

# src/actions/errors/show.cr
class Errors::Show < Lucky::ErrorAction
  disable_cookies
  # ...
end

This will disable writing all cookies, session, and flash messages for this action. If you need to do this for all of your actions, you can add the disable_cookies macro to the action you inherit from (For example the ApiAction).

See a problem? Have an idea for improvement? Edit this page on GitHub