Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Phoenix: Trying to connect to Channel but getting a not Route found for GET /websocket error

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?

like image 835
Ole Spaarmann Avatar asked Jul 12 '16 00:07

Ole Spaarmann


Video Answer


1 Answers

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.

like image 68
Ole Spaarmann Avatar answered Oct 13 '22 12:10

Ole Spaarmann