Server-rendered pages in your elm-pages
can set cookies. elm-pages
provides two high-level ways to work with cookies:
Server.Session.withSession
provides a high-level way to manage key-value pairs of data using cookie storage,
whereas Server.Response.withSetCookieHeader
gives a more low-level tool for setting cookies. It's often best to use the
most high-level tool that will fit your use case.
You can learn more about the basics of cookies in the Web Platform in these helpful MDN documentation pages:
{ name : String
, value : String
, options : Options
}
setCookie : String -> String -> Options -> SetCookie
Create a SetCookie
record with the given name, value, and [Options
](Options]. To add a Set-Cookie
header, you can
pass this value with Server.Response.withSetCookieHeader
. Or for more low-level
uses you can stringify the value manually with toString
.
Usually you'll want to start by creating default Options
with options
and then overriding defaults using the with...
helpers.
import Server.SetCookie as SetCookie
options : SetCookie.Options
options =
SetCookie.options
|> SetCookie.nonSecure
|> SetCookie.withMaxAge 123
|> SetCookie.makeVisibleToJavaScript
|> SetCookie.withoutPath
|> SetCookie.setCookie "id" "a3fWa"
{ expiration : Maybe Time.Posix
, visibleToJavaScript : Basics.Bool
, maxAge : Maybe Basics.Int
, path : Maybe String
, domain : Maybe String
, secure : Basics.Bool
, sameSite : Maybe SameSite
}
The set of possible configuration options. You can configure this record directly, or use the with...
helpers.
options : Options
Initialize the default SetCookie
Options
. Can be configured directly through a record update, or with withExpiration
, etc.
Possible values for the cookie's same-site value.
The default option is Lax
(Lax does not send
cookies in cross-origin requests so it is a good default for most cases, but Strict
is even more restrictive).
Override the default option using withSameSite
.
withSameSite : SameSite -> Options -> Options
The default SameSite policy is Lax if one is not explicitly set. See the SameSite section in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#attributes.
withImmediateExpiration : Options -> Options
Sets Expires
to Time.millisToPosix 0
,
which effectively tells the browser to delete the cookie immediately (by giving it an expiration date in the past).
makeVisibleToJavaScript : Options -> Options
The default option in this API is for HttpOnly cookies https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#httponly.
Cookies can be exposed so you can read them from JavaScript using Document.cookie
. When this is intended and understood
then there's nothing unsafe about that (for example, if you are setting a darkMode
cookie and what to access that
dynamically). In this API you opt into exposing a cookie you set to JavaScript to ensure cookies aren't exposed to JS unintentionally.
In general if you can accomplish your goal using HttpOnly cookies (i.e. not using makeVisibleToJavaScript
) then
it's a good practice. With server-rendered elm-pages
applications you can often manage your session state by pulling
in session data from cookies in a BackendTask
(which is resolved server-side before it ever reaches the browser).
nonSecure : Options -> Options
Secure (only sent over https, or localhost on http) is the default. This overrides that and
removes the Secure
attribute from the cookie.
withDomain : String -> Options -> Options
Sets the Set-Cookie
's Domain
.
withExpiration : Time.Posix -> Options -> Options
withMaxAge : Basics.Int -> Options -> Options
Sets the Set-Cookie
's Max-Age
.
withPath : String -> Options -> Options
Sets the Set-Cookie
's Path
.
The default value is /
, which will match any sub-directories or the root directory. See also `withoutPath
withoutPath : Options -> Options
If the server omits the Path attribute, the user agent will use the "directory" of the request-uri's path component as the default value.
Source: https://www.rfc-editor.org/rfc/rfc6265. See https://stackoverflow.com/a/43336097.
toString : SetCookie -> String
Usually you'll want to use Server.Response.withSetCookieHeader
instead.
This is a low-level helper that's there in case you want it but most users will never need this.