How do I pass connection-time websocket parameters to Phoenix from Elm?

霸气de小男生 提交于 2019-12-08 04:03:52

问题


I was following along Programming Phoenix but using Elm for my front end, rather than Javascript. The second part of that book describes how to use websockets. The book's running example has you create an authentication token for the client side to pass to Phoenix at connection creation time. The Javascript Socket class provided with Phoenix allows that, but there's no obvious way to do it in Elm (as of 0.17 and the date of this question).


回答1:


  1. As in the book, make the token visible to Javascript by attaching it to window.

    <script>window.auth_token = "<%= assigns[:auth_token] %>"</script>
    
  2. In web/static/js/app.js, you'll have code that starts Elm. Pass the token there.

    const c4uDiv = document.querySelector('#c4u-target');
    if (c4uDiv) {
      Elm.C4u.embed(c4uDiv, {authToken: window.auth_token});
    }
    
  3. On the Elm side, you'll use programWithFlags instead of program.
  4. Your init function will take a flags argument. (I'm using the Navigation library for a single-page app, which is why there's a PageChoice argument as well.)

    type alias Flags =
      { authToken : String
      }
    
    init : Flags -> MyNav.PageChoice -> ( Model, Cmd Msg )
    
  5. Within init, tack on the token as a URI query pair. Note that you have to uri-encode because the token contains odd characters. Here's the crude way to do that. Note: I am using the elm-phoenix-socket library below, but the same hackery would be required with others.

      let
        uri = "ws://localhost:4000/socket/websocket?auth_token=" ++
              (Http.uriEncode flags.authToken)
      in
        uri
        |> Phoenix.Socket.init
        |> Phoenix.Socket.withDebug
        |> Phoenix.Socket.on "ping" "c4u" ReceiveMessage
    



回答2:


I got here by a Tweet by Brian, about encoding from Elm. In this case I like to handle it from the JavaScript side. I tried to replicate the way the Phoenix client sets it up. Instead of passing the token I passed the complete endpoint...

I've put the token in JSON a hash

 <script id="app-json" type="application/json"><%= raw @json %></script>

Which I read on the client, and pass to the Elm embed

 var data = JSON.parse(document.getElementById("app-json").innerHTML)

 var token = encodeURIComponent(data.token)

 var elm = window.Elm.App.embed(document.getElementById("elm-container"), {
    socketEndpoint: "ws://" + window.location.host + "/socket/websocket?token=" + token
  })


来源:https://stackoverflow.com/questions/40475348/how-do-i-pass-connection-time-websocket-parameters-to-phoenix-from-elm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!