我在这个SO问题中了解到,目前没有简单的方法可以在Elm中将基于cookie的CSRF令牌转换为HTTP请求标头。因此,要编写一个能很好地与Django Rest Framework后端配合使用的单页应用程序(SPA(,我需要从相应的cookie值中手动检索CSRF令牌。
如何在Elm中检索cookie值?Elm是否通过一些命令为此提供运行时支持?还是我需要使用纯JavaScript检索cookie,并通过端口将其提供给ELM SPA?
从Elm 0.9开始,您需要使用端口从JavaScript中读取cookie,并将其传递回Elm应用程序。
在我的申请中,我会做以下事情。我从Elm定义了一个fetchCsrfToken
端口,用来调用读取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/,太神奇了!