Phoenix: Trying to connect to Channel but getting

2020-03-02 05:11发布

I'm trying to hook up an Angular 2 frontend to a Phoenix app using Channels (Websockets). They are completely seperate and run on different ports on localhost (phoenix on 4000, angular 2 on 5555). Strangely I'm getting a (Phoenix.Router.NoRouteError) no route found for GET /websocket (MyApp.Router) error on the backend. And a code 1006 error on the frontend:

WebSocket connection to 'ws://localhost:4000/websocket?vsn=1.0.0' failed: Error during WebSocket handshake: Unexpected response code: 404.

// endpoint.ex

defmodule MyApp.Endpoint do
  use Phoenix.Endpoint, otp_app: :my_app

  # socket "/socket", MyApp.UserSocket
  socket "/websocket", MyApp.PostSocket

  # Serve at "/" the static files from "priv/static" directory.
  #
  # You should set gzip to true if you are running phoenix.digest
  # when deploying your static files in production.
  plug Plug.Static,
    at: "/", from: :my_app, gzip: false,
    only: ~w(css fonts images js favicon.ico robots.txt)

  # Code reloading can be explicitly enabled under the
  # :code_reloader configuration of your endpoint.
  if code_reloading? do
    socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
    plug Phoenix.LiveReloader
    plug Phoenix.CodeReloader
  end

  plug Plug.RequestId
  plug Plug.Logger

  plug Plug.Parsers,
    parsers: [:urlencoded, :multipart, :json],
    pass: ["*/*"],
    json_decoder: Poison

  plug Plug.MethodOverride
  plug Plug.Head

  plug Plug.Session,
    store: :cookie,
    key: "_my_app_key",
    signing_salt: "qCSHk+9O"

    plug CORSPlug, [
      origin: "http://localhost:5555",
      headers: ["X-Auth-Token" | CORSPlug.defaults[:headers]]
    ]

  plug MyApp.Router
end

PostSocket:

defmodule MyApp.PostSocket do
  use Phoenix.Socket

  ## Channels
  channel "post:*", MyApp.PostChannel

  ## Transports
  transport :websocket, Phoenix.Transports.WebSocket
  transport :longpoll, Phoenix.Transports.LongPoll


  def connect(_params, socket) do
    {:ok, socket}
  end

  def id(_socket), do: nil
end

On the frontend, using the phoenix js client:

var socket = new Socket("ws://localhost:4000", {
  logger: ((kind, msg, data) => { console.log(`${kind}: ${msg}`, data) }),
  transport: WebSocket
});
socket.connect();

Does anyone know what's going on?

1条回答
▲ chillily
2楼-- · 2020-03-02 05:58

This question had an answer by José Valim that pointed me in the right direction.

the suffix of the path should be whatever the transport layer is. In this case, it needed /websocket at the end in the implementation.

So in my endpoint I changed the route from /websocket to /socket to prevent confusion:

defmodule TropeApi.Endpoint do
  use Phoenix.Endpoint, otp_app: :trope_api

  socket "/socket", TropeApi.PostSocket

  # ...

end

And then changed the js implementation to reflect that. I also added the transport parameter to the options (just to mention in case this has anything to do with it, which I don't think).

var socket = new Socket("ws://localhost:4000/socket", {
  logger: ((kind, msg, data) => { console.log(`${kind}: ${msg}`, data) }),
  transport: WebSocket
});
socket.connect();

The connection now goes to ws://localhost:4000/socket/websocket. The last part (websocket) let to some confusion for me but was cleared up now.

查看更多
登录 后发表回答