在 Phoenix Framework 中使用自定义序列化程序,例如 MessagePack

Use custom serializer like MessagePack with Phoenix Framework

凤凰 1.3
使用 Erlang 20

编译的 Elixir 1.5.2

我有一个 Android 移动应用程序,它通过 HTTP 服务器发送和接收 MsgPack。现在我们计划在某些部分集成Phoenix框架。但是专门发送二进制文件 MsgPack 在 Phoenix 框架上很麻烦。

如何在 Phoenix 中使用 MsgPack 等自定义(反)序列化程序?

如果有任何相关性: 1. 使用 MsgPax 库
2. Checked this link 在 stoiximan.gr

我用 MsgPax 来做这个,效果很好。首先将其添加到您的 mix.exs 文件中。

接下来,要使用自定义序列化程序,您必须在 the transport function 的 user_socket.ex 文件中指定它,如下所示:

defmodule YourApp.UserSocket do
  use Phoenix.Socket

  # Your channels here

  # Take out whichever version you're not using
  ## Transports for Phoenix 1.2
  transport :websocket, Phoenix.Transports.WebSocket, timeout: 45_000,
            serializer: YourApp.MsgpaxSerializer
  ## Transports for Phoenix 1.3
  transport :websocket, Phoenix.Transports.WebSocket, timeout: 45_000,
            serializer: [{YourApp.MsgpaxSerializer, "~> 2.0.0"}]

  # Other user socket stuff
end

然后,作为 according to the docs, your serializer has to have 3 functions: decode!/2, encode!/1, and fastlane!/1. So, copying mostly from phoenix's own implementation,您的序列化程序可能看起来像这样:

defmodule YourApp.MsgpaxSerializer do
  @behaviour Phoenix.Transports.Serializer

  alias Phoenix.Socket.Reply
  alias Phoenix.Socket.Message
  alias Phoenix.Socket.Broadcast

  def fastlane!(%Broadcast{} = msg) do
    msg = %Message{topic: msg.topic, event: msg.event, payload: msg.payload}

    {:socket_push, :binary, encode_to_binary(msg)}
  end

  def encode!(%Reply{} = reply) do
    msg = %Message{
      topic: reply.topic,
      event: "phx_reply",
      ref: reply.ref,
      payload: %{status: reply.status, response: reply.payload}
    }
    {:socket_push, :binary, encode_to_binary(msg)}
  end
  def encode!(%Message{} = msg) do
    {:socket_push, :binary, encode_to_binary(msg)}
  end

  defp encode_to_binary(msg) do
    msg |> Map.from_struct() |> Msgpax.pack!()
  end

  def decode!(message, _opts) do
    message
    |> Msgpax.unpack!()
    |> Phoenix.Socket.Message.from_map!()
  end
end

最后,如果您正在对结构进行编码,则可能必须将 @derive Msgpax.Packer 属性添加到包含结构的模块中,如 Msgpax's documentation 中所述。