Как открыть собственный веб-сокет Elixir с помощью WebSockex

Я вижу базовый пример библиотеки WebSockex для Elixir здесь, но он не объясняет, как я могу предоставить мой собственный веб-сокет в Интернет. На этот вопрос есть ответы, объясняющие как общаться с существующим веб-сокетом извне, но я хочу открыть свой собственный веб-сокет. На самом деле я использую websockex как часть приложения Phoenix, так что, возможно, здесь могут помочь кусочки Phoenix?

Я, очевидно, знаю комбинацию ip:port моего приложения phoenix, поэтому, учитывая это, как мне открыть веб-сокет websockex на этом ip:port? Другими словами, что я должен передать в качестве URL-адреса? в этом базовом примере кода:

defmodule WebSocketExample do
  use WebSockex

  def start_link(url, state) do
    WebSockex.start_link(url, __MODULE__, state)
  end

  def handle_frame({type, msg}, state) do
    IO.puts "Received Message - Type: #{inspect type} -- Message: #{inspect msg}"
    {:ok, state}
  end

  def handle_cast({:send, {type, msg} = frame}, state) do
    IO.puts "Sending #{type} frame with payload: #{msg}"
    {:reply, frame, state}
  end
end

Обратите внимание, что мне нужно предоставить необработанный веб-сокет, а не канал Phoenix, поскольку потребитель не понимает каналы Phoenix. Если Phoenix сможет предоставить необработанный веб-сокет, я тоже рассмотрю это решение.

Если ни Phoenix, ни WebSockex не могут помочь, какие у меня есть варианты?


person Thomas Browne    schedule 28.02.2021    source источник


Ответы (2)


Websockex - это клиентская библиотека, я не думаю, что в ней есть какой-либо код для раскрытия веб-сокета. Поскольку вы уже используете phoenix, вы, вероятно, можете делать то, что вам нужно, с каналами phoenix.

Если вы используете cowboy (и, вероятно, так и есть, поскольку это значение по умолчанию), вы также можете использовать его для предоставления необработанного веб-сокета. Тем не менее, это требует некоторой возни с маршрутизацией. Вам нужно будет заменить YourAppWeb.Endpoint на ручную настройку cowboy:

{
  Plug.Cowboy,
  scheme: :http,
  plug: YourAppWeb.Endpoint,
  options: endpoint_options(),
  dispatch: [
    _: [
      # Dispatch paths beginning with /ws to a websocket handler
      {"/ws/[...]", YourApp.WebsocketHandler, []},
      # Dispatch other paths to the phoenix endpoint
      {:_, Plug.Cowboy.Handler, {YourAppWeb.Endpoint, endpoint_options()}}
    ]
  ]
}

Честно говоря, я сделал это только с необработанным plug, поэтому вам может потребоваться преобразовать конечную точку в Plug вместо Phoenix.Endpoint. Затем вам нужно реализовать YourApp.WebsocketHandler для соответствия API cowboy и выполнить обновление веб-сокета (и обрабатывать отправку/получение сообщений), как описано в документации по ковбоям. Вы также можете увидеть эту суть для более подробного примера.

person Paweł Obrok    schedule 01.03.2021
comment
Мне нужно открыть необработанный веб-сокет, а не канал феникса, так как данные будут потребляться приложением, которое не понимает каналы феникса. Может ли phoenix выставить необработанный веб-сокет? - person Thomas Browne; 01.03.2021
comment
Я добавил некоторую информацию о том, как выставить необработанный сокет с помощью cowboy, хотя мне кажется, что это более сложно, чем либо реализация частей протокола phoenix самостоятельно, либо просто копирование deps/phoenix/assets/js/phoenix.js в ваш код, если вам нужен очень низкий уровень. техническое решение - это всего 1,6 тыс. строк в неминифицированном виде. - person Paweł Obrok; 01.03.2021
comment
Также рассмотрите Phoenix.Socket.Transport для реализации другого протокола. Вероятно, проще начать, чем добавлять cowboy конфигурацию вручную. - person Maarten van Vliet; 08.03.2021

WebSockex реализует множество обратных вызовов, включая, помимо прочего, WebSockex.handle_connect/2. Он содержит WebSockex.Conn в состоянии и передает его всем обратным вызовам.

WebSockex.Conn — это старая добрая структура, наличие поля socket.

Таким образом, из любого обратного вызова (я бы сделал это из WebSockex.handle_connect/2) вы можете поделиться этим сокетом с процессом, которому он нужен, и использовать его оттуда.


Также вы можете позаимствовать некоторые внутренности и проверить, как работает соединение создается.

Вы увидите, что он использует WebSockex.Conn.new/2, который возвращает инициализированное соединение, которое , в свою очередь, держит сокет. В этом случае вы будете обязаны вручную контролировать процесс, удерживающий сокет.


Сила OSS в том, что все ответы можно получить одним щелчком мыши, а не вопросами.

person Aleksei Matiushkin    schedule 01.03.2021
comment
Итак, то, что вы здесь объясняете, позволит мне открыть веб-сокет для Интернета, верно? Потому что это то, что мне нужно. Потребителем будет Javascript Node Red (flows.nodered.org/ node/node-red-contrib-websocket-auth0) - person Thomas Browne; 01.03.2021
comment
Это объясняет, как добраться до базового необработанного сокета. Это то, что спросили. JS может отлично читать из сокетов Phoenix, насколько мне известно. - person Aleksei Matiushkin; 01.03.2021
comment
JS нужно загружать код библиотеки phoenix для чтения с каналов Phoenix, а это пока недоступно в библиотеке Node Red, и я не хочу писать такую ​​тяжеловесную надстройку. Итак, я хотел спросить, как открыть необработанный веб-сокет в Интернете, используя websockex, а не только как получить доступ к необработанному сокету. Поэтому я отредактирую свой вопрос, чтобы сделать это явным. - person Thomas Browne; 01.03.2021