# Websocket server in Elixir or phoenix

**URL:** <https://forum.elixirforum.com/t/websocket-server-in-elixir-or-phoenix/51906>\
**Category:** Questions\
**Tags:** phoenix, websockets\
**Created:** [November 19, 2022, 8:42pm UTC](https://forum.elixirforum.com/t/websocket-server-in-elixir-or-phoenix/51906 "2022-11-19T20:42:01Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![LegitStack](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/legitstack/32/5086_2.png) [@LegitStack](https://forum.elixirforum.com/u/LegitStack)\
**Post date:** [November 19, 2022, 8:42pm UTC](https://forum.elixirforum.com/t/websocket-server-in-elixir-or-phoenix/51906/1 "2022-11-19T20:42:01Z")

</div>

I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that smart I thought I’d go as high level as possible.

I found this thread:

> [@Phoenix Channels (ws) without frontend](https://forum.elixirforum.com/t/phoenix-channels-ws-without-frontend/46200):
>
> I am trying to develop a small websocket API (as a testbed first) but without using the Phoenix frontend (that socket.js). I need it to communicate to any ws client, not related to Elixir/Phoenix, just exchanging json messages. Of course I started from the standard, ubiquitous tutorial found online, that one with a simple chat, by modifying it: setup Phoenix project – standard install/config, then: mix phx.gen.channel room started & tested the Phoenix server installation in the browser – run…

and this one:

> [@Phx\_raws - Raw websocket on top of Phoenix](https://forum.elixirforum.com/t/phx-raws-raw-websocket-on-top-of-phoenix/9362):
>
> In a Phoenix-based project, it is rather tedious to get a raw cowboy websocket working manually, as one is required to set-up a custom dispatch as well as to handle the socket itself. Therefore, after a few hours of testing and reading through the source code, I have come up with a solution that follows Phoenix’ semantics nicely. Repository: [https://github.com/satom99/phx\_raws](https://github.com/satom99/phx_raws) Contributions are more than welcome, especially to keep it updated and prevent it from breaking as Phoenix continues t…

and forked his code to:  
[https://github.com/SatoriNetwork/phx\_raws](https://github.com/SatoriNetwork/phx_raws)

I as I was bringing it up to date I ran into this issue:

> Phoenix.Socket.Transport.connect/6 is undefined or private. Did you mean:
> 
> ```
> * connect_info/3Elixir
> 
> ```
> 
> Call to missing or unexported function ‘Elixir.Phoenix.Socket.Transport’:connect/6ElixirLS Dialyzer

on this line:  
`case Transport.connect(endpoint, handler, transport, __MODULE__ , nil, conn.params) do`

so after consulting the [docs](https://hexdocs.pm/phoenix/Phoenix.Socket.Transport.html#c:connect/1), which I don’t understand I came up with this, which I;m sure is wildly incorrect as well:

```elixir
case Transport.connect(
          %{:endpoint=>endpoint, :transport=>transport, :params=>conn.params, :options=>[
            handler: handler, __MODULE__ : __MODULE__ , serializer: nil]}) do

```

But it told me I shouldn’t use this function anyway:

> Phoenix.Socket.Transport.connect/1 is undefined or private. Did you mean:
> 
> ```
> * connect_info/3Elixir
> 
> ```
> 
> Call to missing or unexported function ‘Elixir.Phoenix.Socket.Transport’:connect/1ElixirLS Dialyzer

I think the code is almost updated, but what do I have to do to get it to a working state?

---

<div class="post-metadata">

**Author:** ![ruslandoga](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ruslandoga/32/22193_2.png) [@ruslandoga](https://forum.elixirforum.com/u/ruslandoga)\
**Post date:** [November 20, 2022, 1:44pm UTC](https://forum.elixirforum.com/t/websocket-server-in-elixir-or-phoenix/51906/2 "2022-11-20T13:44:32Z")

</div>

👋

Using `cowboy` might be easier than you think. [Here’s](https://github.com/ruslandoga/backend-for-ios-ws-experiments) a small example of how it could be done. The important bits are the [plug child spec](https://github.com/ruslandoga/backend-for-ios-ws-experiments/blob/e126a17f45b0382533a076b1375b83ec2f8907b7/lib/w/application.ex#L9-L10) and the [module implementing cowboy\_websocket behaviour.](https://github.com/ruslandoga/backend-for-ios-ws-experiments/blob/master/lib/web/socket.ex) You can ignore the `Web.UserSocket` and “pubsub” specifics.

[More info on `cowboy_websocket` behaviour.](https://ninenines.eu/docs/en/cowboy/2.6/manual/cowboy_websocket/)

---

<div class="post-metadata">

**Author:** ![josevalim](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/32/1787_2.png) [@josevalim](https://forum.elixirforum.com/u/josevalim)\
**Post date:** [November 20, 2022, 2:01pm UTC](https://forum.elixirforum.com/t/websocket-server-in-elixir-or-phoenix/51906/3 "2022-11-20T14:01:15Z")

</div>

There is a simpler API in Phoenix for custom websockets, you can follow the example here:

> **[Phoenix.Socket.Transport — Phoenix v1.8.8](https://phoenix.hexdocs.pm/Phoenix.Socket.Transport.html)**

---

<div class="post-metadata">

**Author:** ![RooSoft](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/roosoft/32/23241_2.png) [@RooSoft](https://forum.elixirforum.com/u/RooSoft)\
**Post date:** [February 1, 2023, 5:50pm UTC](https://forum.elixirforum.com/t/websocket-server-in-elixir-or-phoenix/51906/4 "2023-02-01T17:50:53Z")

</div>

Is there a way to make this thing listen to the root path, such as ws://localhost?

From what I understand, it listens to the `/websocket` path if the endpoint’s socket is configured like so `socket "/", RelayWeb.Sockets.EchoSocket`.

I’ve seen comments saying it’s better for whatever reason. Thing is, I have to fill a spec that requires that the websockets endpoint answers to the root path and I have no idea how to do that with `Phoenix.Socket.Transport` as we stand.

---

<div class="post-metadata">

**Author:** ![RooSoft](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/roosoft/32/23241_2.png) [@RooSoft](https://forum.elixirforum.com/u/RooSoft)\
**Post date:** [February 1, 2023, 6:21pm UTC](https://forum.elixirforum.com/t/websocket-server-in-elixir-or-phoenix/51906/5 "2023-02-01T18:21:41Z")

</div>

Also would like to know how to implement heartbeat such as sending a PING and expecting a PONG after a while instead of simply closing the connection after 60s of inactivity.

---

<div class="post-metadata">

**Author:** ![RooSoft](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/roosoft/32/23241_2.png) [@RooSoft](https://forum.elixirforum.com/u/RooSoft)\
**Post date:** [February 1, 2023, 6:30pm UTC](https://forum.elixirforum.com/t/websocket-server-in-elixir-or-phoenix/51906/6 "2023-02-01T18:30:52Z")

</div>

Figured out this part

```elixir
socket("/", RelayWeb.Sockets.EchoSocket, websocket: [path: ""])

```

---

<div class="post-metadata">

**Author:** ![RooSoft](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/roosoft/32/23241_2.png) [@RooSoft](https://forum.elixirforum.com/u/RooSoft)\
**Post date:** [February 1, 2023, 7:32pm UTC](https://forum.elixirforum.com/t/websocket-server-in-elixir-or-phoenix/51906/7 "2023-02-01T19:32:45Z")

</div>

Also figured out…

In init/1,

```elixir
Process.send_after(self(), :ping, ping_timeout)

```

Then, add a handle\_info

```elixir
  @impl true
  def handle_info(:ping, %{options: options} = state) do
    ping_timeout = Keyword.get(options, :ping)

    Process.send_after(self(), :ping, ping_timeout)

    {:push, {:ping, ""}, state}
  end

```

Will suggest the peer has to send a `PONG`, and if it does, that will count as a communication and thus will reset the timeout.

---

<div class="post-metadata">

**Author:** ![ku1ik](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ku1ik/32/22733_2.png) [@ku1ik](https://forum.elixirforum.com/u/ku1ik)\
**Post date:** [February 23, 2023, 5:30pm UTC](https://forum.elixirforum.com/t/websocket-server-in-elixir-or-phoenix/51906/8 "2023-02-23T17:30:29Z")

</div>

Thank you @RooSoft! I was trying to solve these 2 specific problems (path, ping) myself and your solutions to both work perfectly.

---

<div class="post-metadata">

**Author:** ![mtrudel](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mtrudel/32/28190_2.png) [@mtrudel](https://forum.elixirforum.com/u/mtrudel)\
**Post date:** [February 23, 2023, 6:31pm UTC](https://forum.elixirforum.com/t/websocket-server-in-elixir-or-phoenix/51906/9 "2023-02-23T18:31:20Z")

</div>

Careful that sending pongs in response to client pings is explicitly handled for you by the underlying server in the WebSock world: [WebSock — WebSock v0.5.3](https://hexdocs.pm/websock/WebSock.html#c:handle_control/2)
