Skip to content

Commit

Permalink
Switch from websockex to gun
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric Saxby committed Jun 10, 2021
1 parent 2f0c330 commit 49e522c
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 35 deletions.
30 changes: 18 additions & 12 deletions lib/playwright/browser_type.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,8 @@ defmodule Playwright.BrowserType do
def connect(ws_endpoint) do
{:ok, connection} = new_session(Transport.WebSocket, [ws_endpoint])

browser_guid =
case wait_for_browser(connection, "chromium") do
%{initializer: %{version: "91." <> _}} ->
playwright = Connection.get(connection, {:guid, "Playwright"})
%{guid: guid} = playwright.initializer.preLaunchedBrowser
guid

%{initializer: %{version: "87." <> _}} ->
remote_browser = Connection.get(connection, {:guid, "remoteBrowser"})
%{guid: guid} = remote_browser.initializer.browser
guid
end
%{initializer: %{version: version}} = wait_for_browser(connection, "chromium")
browser_guid = browser_from_chromium(connection, version)

browser = Connection.get(connection, {:guid, browser_guid})
{connection, browser}
Expand Down Expand Up @@ -83,4 +73,20 @@ defmodule Playwright.BrowserType do
Connection.wait_for_channel_messages(connection, "Browser")
|> Enum.find(&(&1.initializer.name == name))
end

defp browser_from_chromium(connection, version) do
version = version |> String.split(".") |> Enum.take(3) |> Enum.join(".")

case Version.compare(version, "90.0.0") do
:gt ->
playwright = Connection.get(connection, {:guid, "Playwright"})
%{guid: guid} = playwright.initializer.preLaunchedBrowser
guid

_ ->
remote_browser = Connection.get(connection, {:guid, "remoteBrowser"})
%{guid: guid} = remote_browser.initializer.browser
guid
end
end
end
88 changes: 73 additions & 15 deletions lib/playwright/client/transport/websocket.ex
Original file line number Diff line number Diff line change
@@ -1,43 +1,101 @@
defmodule Playwright.Client.Transport.WebSocket do
@moduledoc false
use WebSockex
use GenServer
alias Playwright.Connection
require Logger

# API
# ---------------------------------------------------------------------------

defstruct(connection: nil)
defstruct([
:connection,
:gun,
:gun_process_monitor,
:gun_stream_ref
])

def start_link([ws_endpoint, connection]) do
WebSockex.start_link(ws_endpoint, __MODULE__, %__MODULE__{connection: connection}, [
{:socket_recv_timeout, 120_000}
])
GenServer.start_link(__MODULE__, [ws_endpoint, connection])
end

def start_link!(args) do
{:ok, pid} = start_link(args)
pid
end

@impl GenServer
def init([ws_endpoint, connection]) do
uri = URI.parse(ws_endpoint)

with {:ok, gun_pid} <- :gun.open(to_charlist(uri.host), port(uri)),
{:ok, _protocol} <- :gun.await_up(gun_pid),
stream_ref <- :gun.ws_upgrade(gun_pid, uri.path),
:ok <- wait_for_ws_upgrade() do
ref = Process.monitor(gun_pid)

{:ok,
__struct__(
connection: connection,
gun: gun_pid,
gun_process_monitor: ref,
gun_stream_ref: stream_ref
)}
end
end

@spec send_message(pid(), binary()) :: :ok
def send_message(pid, message) do
WebSockex.send_frame(pid, {:text, message})
GenServer.cast(pid, {:send_message, message})
:ok
end

# @impl
# ---------------------------------------------------------------------------

@impl WebSockex
def handle_connect(_conn, state) do
{:ok, state}
@impl true
def handle_cast({:send_message, message}, state) do
:gun.ws_send(state.gun, {:text, message})
{:noreply, state}
end

@impl true
def handle_info({:gun_ws, _gun_pid, _stream_ref, frame}, state) do
case frame do
{:text, data} ->
debug("frame: #{data}")
Connection.recv(state.connection, frame)
end
{:noreply, state}
end

@impl WebSockex
def handle_frame(frame, %{connection: connection} = state) do
{:text, data} = frame
Logger.debug("websocket frame: #{data}")
Connection.recv(connection, frame)
def handle_info({:DOWN, _ref, :process, pid, reason}, state) do
warn("Process went down: #{inspect(pid)}")
{:stop, reason, state}
end

defp port(%{port: port}) when not is_nil(port), do: port
defp port(%{scheme: "ws"}), do: 80
defp port(%{scheme: "wss"}), do: 443

defp transport(%{scheme: "wss"}), do: :http
defp transport(%{scheme: "ws"}), do: :http

{:ok, state}
defp wait_for_ws_upgrade do
receive do
{:gun_upgrade, _pid, _stream_ref, ["websocket"], _headers} ->
:ok

{:gun_response, _pid, _stream_ref, _, status, _headers} ->
{:error, status}

{:gun_error, _pid, _stream_ref, reason} ->
{:error, reason}
after
1000 ->
exit(:timeout)
end
end

defp debug(msg), do: Logger.debug("[websocket@#{inspect(self())}] #{msg}")
defp warn(msg), do: Logger.warn("[websocket@#{inspect(self())}] #{msg}")
end
5 changes: 3 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ defmodule Playwright.MixProject do
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:cowlib, "~> 2.11.0", override: true},
{:credo, "~> 1.4", only: [:dev, :test], runtime: false},
{:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false},
{:ex_doc, "~> 0.24", only: :docs, runtime: false},
{:gun, "~> 1.3"},
{:jason, "~> 1.2"},
{:plug, "~> 1.11.1", only: [:dev, :test]},
{:plug_cowboy, "~> 2.5.0", only: [:dev, :test]},
{:websockex, "~> 0.4.3"}
{:plug_cowboy, "~> 2.5.0", only: [:dev, :test]}
]
end
end
7 changes: 1 addition & 6 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,18 @@
"dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"},
"earmark_parser": {:hex, :earmark_parser, "1.4.13", "0c98163e7d04a15feb62000e1a891489feb29f3d10cb57d4f845c405852bbef8", [:mix], [], "hexpm", "d602c26af3a0af43d2f2645613f65841657ad6efc9f0e361c3b6c06b578214ba"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"erlexec": {:hex, :erlexec, "1.18.11", "46cc6aa4ac94f0ff39611f28400b48fa794bbbdec8722202155374981da25682", [:rebar3], [], "hexpm", "2ba928f1bdf74e098c413465f109c10b5d1e1359568eb7bf4c99f91ac983b8ff"},
"ex_doc": {:hex, :ex_doc, "0.24.2", "e4c26603830c1a2286dae45f4412a4d1980e1e89dc779fcd0181ed1d5a05c8d9", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "e134e1d9e821b8d9e4244687fb2ace58d479b67b282de5158333b0d57c6fb7da"},
"exexec": {:hex, :exexec, "0.2.0", "a6ffc48cba3ac9420891b847e4dc7120692fb8c08c9e82220ebddc0bb8d96103", [:mix], [{:erlexec, "~> 1.10", [hex: :erlexec, repo: "hexpm", optional: false]}], "hexpm", "312cd1c9befba9e078e57f3541e4f4257eabda6eb9c348154fe899d6ac633299"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"iconv": {:hex, :iconv, "1.0.12", "b0a7ec542ee0319848a53410c72380f628a39f7b694c60cbb6e02d9eb4322a3a", [:rebar3], [{:p1_utils, "1.0.21", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "44d1185eb7f80da439c4d0664387d847844ff8d212387b45529309015b77e38f"},
"gun": {:hex, :gun, "1.3.3", "cf8b51beb36c22b9c8df1921e3f2bc4d2b1f68b49ad4fbc64e91875aa14e16b4", [:rebar3], [{:cowlib, "~> 2.7.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "3106ce167f9c9723f849e4fb54ea4a4d814e3996ae243a1c828b256e749041e0"},
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
"makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
"mime": {:hex, :mime, "1.6.0", "dabde576a497cef4bbdd60aceee8160e02a6c89250d6c0b29e56c0dfb00db3d2", [:mix], [], "hexpm", "31a1a8613f8321143dde1dafc36006a17d28d02bdfecb9e95a880fa7aabd19a7"},
"nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
"p1_utils": {:hex, :p1_utils, "1.0.21", "9d6244bbd4af881e85af71655e8be5720b5b965b1bdd51a35c7871fd4142af9a", [:rebar3], [], "hexpm", "4b9b90e5863f5fed17f06427ba99b2dc37b216e4dd1308891f0903745e2fccbd"},
"plug": {:hex, :plug, "1.11.1", "f2992bac66fdae679453c9e86134a4201f6f43a687d8ff1cd1b2862d53c80259", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "23524e4fefbb587c11f0833b3910bfb414bf2e2534d61928e920f54e3a1b881f"},
"plug_cowboy": {:hex, :plug_cowboy, "2.5.0", "51c998f788c4e68fc9f947a5eba8c215fbb1d63a520f7604134cab0270ea6513", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5b2c8925a5e2587446f33810a58c01e66b3c345652eeec809b76ba007acde71a"},
"plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"},
"porcelain": {:hex, :porcelain, "2.0.3", "2d77b17d1f21fed875b8c5ecba72a01533db2013bd2e5e62c6d286c029150fdc", [:mix], [], "hexpm", "dc996ab8fadbc09912c787c7ab8673065e50ea1a6245177b0c24569013d23620"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
"telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"},
"websockex": {:hex, :websockex, "0.4.3", "92b7905769c79c6480c02daacaca2ddd49de936d912976a4d3c923723b647bf0", [:mix], [], "hexpm", "95f2e7072b85a3a4cc385602d42115b73ce0b74a9121d0d6dbbf557645ac53e4"},
}

0 comments on commit 49e522c

Please sign in to comment.