I've learned in this SO question that there currently is no simple way to turn cookie-based CSRF tokens into HTTP request headers in Elm. Thus, to write a single page application (SPA) that works nicely with a Django Rest Framework backend, I need to manually retrieve the CSRF-Token from the corresponding cookie value.
How do I retrieve a cookie value in Elm? Does Elm provide runtime support for this via some Command? Or do I need to retrieve the cookie using plain JavaScript and provide it to the ELM SPA via a port?
As of Elm 0.19, you need to use Ports to read the cookie from JavaScript and pass it back to the Elm application.
In my application, I do the following. I define a fetchCsrfToken
port that I use from Elm to call a JavaScript function that reads the cookie. That function then triggers a callback to Elm via a csrfTokenReceiver
port. My Elm application subscribes to that event via subscriptions.
-- Ports.elm
port fetchCsrfToken : () -> Cmd msg
port csrfTokenReceiver : (String -> msg) -> Sub msg
-- Main.elm
init : Flags -> Url -> Key -> ( Model, Cmd Msg )
init flags url key =
-- ...
(model, Ports.fetchCsrfToken ())
subscriptions : Model -> Sub Msg
subscriptions model =
Ports.csrfTokenReceiver GotCsrfToken
// index.js
app.ports.fetchCsrfToken.subscribe(function (str) {
const value = getCookie('csrftoken')
if (value === null) {
app.ports.csrfTokenReceiver.send('')
} else {
app.ports.csrfTokenReceiver.send(value)
}
})