cookieselmelm-port

How to read cookies in Elm?


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?


Solution

  • 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)
      }
    })