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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With