Rerouted (regenerated, verified). Same repository and tag, but GitHub now builds the zip with different bytes, so it no longer matches the SHA-1 package.elm-lang.org recorded. The Lamdera package server serves a copy recovered from https://github.com/dillonkearns/elm-pages-v3-beta.
What we checked: Tag 8.0.0 is still on github.com/dillonkearns/elm-pages-v3-beta; its commit b7735572454e is from 2023-01-17 05:49 UTC, before the version was published (2023-01-17 05:52 UTC); elm.json is byte-identical to package.elm-lang.org's; the exposed modules match docs.json; the zip's SHA-1 is not the published one (GitHub's zip no longer comes out byte for byte the same), so the contents were checked instead.
The Lamdera compiler uses this copy and prints a one-line notice saying so. elm itself fails to download this version.
Details · package.elm-lang.org's zip: https://github.com/dillonkearns/elm-pages-v3-beta/zipball/8.0.0/
You can manage server state with HTTP cookies using this Server.Session API. Server-rendered pages define a Server.Request.Parser
to choose which requests to respond to and how to extract structured data from the incoming request.
Using these functions, you can store and read session data in cookies to maintain state between requests. For example, TODO:
action : RouteParams -> Request.Parser (BackendTask (Response ActionData ErrorPage))
action routeParams =
MySession.withSession
(Request.formDataWithServerValidation (form |> Form.initCombinedServer identity))
(\nameResultData session ->
nameResultData
|> BackendTask.map
(\nameResult ->
case nameResult of
Err errors ->
( session
|> Result.withDefault Nothing
|> Maybe.withDefault Session.empty
, Response.render
{ errors = errors
}
)
Ok ( _, name ) ->
( session
|> Result.withDefault Nothing
|> Maybe.withDefault Session.empty
|> Session.insert "name" name
|> Session.withFlash "message" ("Welcome " ++ name ++ "!")
, Route.redirectTo Route.Greet
)
)
)The elm-pages framework will manage signing these cookies using the secrets : BackendTask (List String) you pass in.
That means that the values you set in your session will be directly visible to anyone who has access to the cookie
(so don't directly store sensitive data in your session). Since the session cookie is signed using the secret you provide,
the cookie will be invalidated if it is tampered with because it won't match when elm-pages verifies that it has been
signed with your secrets. Of course you need to provide secure secrets and treat your secrets with care.
The first String in secrets : BackendTask (List String) will be used to sign sessions, while the remaining String's will
still be used to attempt to "unsign" the cookies. So if you have a single secret:
Session.withSession
{ name = "mysession"
, secrets =
BackendTask.map List.singleton
(Env.expect "SESSION_SECRET2022-09-01")
, options = cookieOptions
}Then you add a second secret
Session.withSession
{ name = "mysession"
, secrets =
BackendTask.map2
(\newSecret oldSecret -> [ newSecret, oldSecret ])
(Env.expect "SESSION_SECRET2022-12-01")
(Env.expect "SESSION_SECRET2022-09-01")
, options = cookieOptions
}The new secret (2022-12-01) will be used to sign all requests. This API always re-signs using the newest secret in the list
whenever a new request comes in (even if the Session key-value pairs are unchanged), so these cookies get "refreshed" with the latest
signing secret when a new request comes in.
However, incoming requests with a cookie signed using the old secret (2022-09-01) will still successfully be unsigned
because they are still in the rotation (and then subsequently "refreshed" and signed using the new secret).
This allows you to rotate your session secrets (for security purposes). When a secret goes out of the rotation, it will invalidate all cookies signed with that. For example, if we remove our old secret from the rotation:
Session.withSession
{ name = "mysession"
, secrets =
BackendTask.map List.singleton
(Env.expect "SESSION_SECRET2022-12-01")
, options = cookieOptions
}And then a user makes a request but had a session signed with our old secret (2022-09-01), the session will be invalid
(so withSession would parse the session for that request as Nothing). It's standard for cookies to have an expiration date,
so there's nothing wrong with an old session expiring (and the browser will eventually delete old cookies), just be aware of that when rotating secrets.