有没有办法强制从服务器端断开苦艾图订阅?

Posted

技术标签:

【中文标题】有没有办法强制从服务器端断开苦艾图订阅?【英文标题】:Is there a way to force disconnect an absinthe graphql subscription from the server side? 【发布时间】:2021-09-24 15:44:02 【问题描述】:

我正在开发的 Phoenix 应用程序会创建对文档更改的订阅,只要该文档是“公开的”即可。但是,如果有人将他们的文档更改为“私人”,我不希望这些订阅继续接收更新。

我知道如何防止在私人文档上创建新订阅,但我不确定如何从服务器端禁用预先存在的订阅?

【问题讨论】:

【参考方案1】:

您需要为对应于特定用户的每个套接字分配一个 ID。然后你可以这样做:

MyAppWeb.Endpoint.broadcast(socket_id, "disconnect", %)

要将 ID 分配给套接字,请找到执行此操作的模块:

use Absinthe.Phoenix.Socket,
  schema: MyAppWeb.Schema

大概在lib/my_app_web/channels/user_socket.ex

在那个“socket”模块中,你可以这样写你的 ID 回调:

  @impl true
  def id(%
        assigns: %
          absinthe: %
            opts: [
              context: %current_user: current_user
            ]
          
        
      ),
      do: socket_id_for_user(current_user)

  def id(_socket), do: nil

  def socket_id_for_user(%id: id), do: "user_socket:#id"

现在你只需要确保这个 current_user 分配在你的套接字上。

首先,转到您的路由器并将这条线放在任何需要它的管道中(通常只是:api 管道,有时是:browser 管道):

    plug :fetch_current_user

在您的路由器中(或在您喜欢的导入模块中),编写此函数:

  def fetch_current_user(conn, _opts) do
    # I don't know how you do auth so get your user your own way.
    # For me, it usually involves finding their session token in the DB.
    user = get_user_from_conn(conn)

    context = if is_nil(user), do: %, else: %current_user: user

    conn
    |> Absinthe.Plug.assign_context(context)
  end

您可能想在此函数中执行其他操作。 例如,如果您使用 phx_gen_auth,您可能会将 user_token 放入私有分配中。

您现在遇到的主要问题是,如果您通过此套接字发送注销突变,您将在发送响应之前关闭它。很有趣的问题。

在这里讨论:https://elixirforum.com/t/is-there-a-way-to-force-disconnect-an-absinthe-graphql-subscription-from-the-server-side/41042 我的方法不允许您终止特定描述。我所描述的是一种终止整个套接字的方法。使用这种方法,客户端必须在需要时创建一个新的“未经身份验证的”套接字。

【讨论】:

以上是关于有没有办法强制从服务器端断开苦艾图订阅?的主要内容,如果未能解决你的问题,请参考以下文章

Socket服务器端如何检测客户端的连接状态?

如何使用 socket.io 断开所有套接字服务端?

ESP32-IDF05-4 WIFI-MQTT协议基础

SSH 超时断开连接解决办法

socket编程中,服务器如何检测到客户端网络连接的断开.比如说客户端的网线断掉了,从服务端如何能检测到呢l

禁用来自客户端脚本的OPTIONS请求