如何在 Elm 中读取 cookie?

How to read cookies in Elm?

我在 中了解到,目前没有简单的方法可以在 Elm 中将 cookie-based CSRF 令牌转换为 HTTP 请求 headers。因此,要编写与 Django Rest Framework 后端良好配合的单页应用程序 (SPA),我需要从相应的 cookie 值中手动检索 CSRF-Token。

如何在 Elm 中检索 cookie 值? Elm 是否通过某些命令为此提供运行时支持?或者我是否需要使用纯 JavaScript 检索 cookie 并通过端口将其提供给 ELM SPA?

从 Elm 0.9 开始,您需要使用 Ports 从 JavaScript 读取 cookie 并将其传回 Elm 应用程序。

在我的应用程序中,我执行以下操作。我定义了一个 fetchCsrfToken 端口,我使用它从 Elm 调用读取 cookie 的 JavaScript 函数。然后该函数通过 csrfTokenReciever 端口触发对 Elm 的回调。我的 Elm 应用程序通过订阅订阅该事件。

-- Ports.elm

port fetchCsrfToken : () -> Cmd msg
port csrfTokenReciever : (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.csrfTokenReciever GotCsrfToken
// index.js

app.ports.fetchCsrfToken.subscribe(function (str) {
  const value = getCookie('csrftoken')
  if (value === null) {
    app.ports.csrfTokenReciever.send('')
  } else {
    app.ports.csrfTokenReciever.send(value)
  }
})

使用 Elm 0.19.1

第一个解法:

使用 2 个端口、一个订阅和一些 JS/TS 代码,如 @viam0Zah 提到的。


第二种解决方案:

在初始化时将 CSRF 传递到您的标志中

    const app = Elm.Main.init({
      node: document.querySelector("main"),
      flags: {
        csrfToken: getCookie('csrftoken')
      }
    });

将 csrfToken 添加到标志中

type alias Flags =
    { ---
    , csrfToken : String
    }

不要忘记为 csrfToken 添加解码器:

import Json.Decode as D

flagsDecoder : D.Decoder Flags
flagsDecoder =
    D.succeed Flags
        |> ---
        |> D.required "csrfToken" D.string

如果您想要更健壮并扩展两种解决方案的类型安全性 - 标志和端口,您应该查看 https://elm-ts-interop.com/,这太棒了!