广播机制

未匹配的标注

Masonite 提供了一种在应用程序中广播事件的强大方式。可以使用 JavaScript 向客户端收听这些事件。

这些可以是新通知之类的东西,你可以在前端显示而无需重新加载页面。

Masonite 附带一个服务器端驱动程序:Pusher

配置

服务端

广播的服务器端配置在 config/broadcast.py 配置文件中完成。目前有一个可用的驱动程序 Pusher

你应该在 Pusher Channels 上创建一个帐户,然后在您的帐户上创建一个 Pusher 应用程序并获取相关凭据(客户端、app_id、secret)和集群位置名称,并将其放入广播推送选项中。

"pusher": {
    "driver": "pusher",
    "app_id": "3456678"
    "client": "478b45309560f3456211" # key
    "secret": "ab4229346et64aa8908"
    "cluster": "eu",
    "ssl": False,
},

最后确保你安装了 pusher python 包

pip install pusher

客户端

为了能够在浏览器中接收广播事件,你应该安装 Javascript Pusher SDK

在你的页面上包含 pusher-js 脚本标签

<script src="https://js.pusher.com/7.0.3/pusher.min.js"></script>

注意:这是安装 Pusher 的最快方法。但是对于一个真正的应用程序,你通常可以使用构建系统来安装和编译资源,并将使用 npm install pusher-js 安装 Javascript Pusher SDK,然后导入 Pusher 类与 import Pusher from 'pusher-js';

创建一个使用你的凭据配置的 Pusher 实例

const pusher = new Pusher("478b45309560f3456211", {
  cluster: "eu",
});

注意:建议在客户端使用环境变量而不是硬编码凭据。如果你使用 Laravel Mix 来编译资产, 那么你应该在你的环境变量前面加上 MIX_

现在你已准备好订阅频道并收听频道事件。

创建事件

广播事件是继承自 CanBroadcast 的简单类。你可以使用任何类,包括 Masonite Event 类。

广播事件将如下所示:

from masonite.broadcasting import CanBroadcast, Channel

class UserAdded(CanBroadcast):

    def broadcast_on(self):
        return Channel("channel_name")

请注意,发送给客户端的事件名称将是类的名称。这里是 UserAdded

广播事件

You can broadcast the event using the Broadcast facade or by resolving Broadcast class from container.

你可以使用 Broadcast 门面或通过从容器解析 Broadcast 类来广播事件。

你无需创建广播事件即可轻松广播

from masonite.facades import Broadcast

Broadcast.channel('channel_name', "event_name", {"key": "value"})

或者你可以广播之前创建的事件类

from masonite.facades import Broadcast
from app.broadcasts import UserAdded

broadcast.channel(UserAdded())

你也可以在多个频道上广播:

Broadcast.channel(['channel1', 'channel2'], "event_name", {"key": "value"})

提示:这种类型的广播会将所有频道作为公共广播。对于私有和状态频道,请继续阅读。

监听事件

在本节中,我们将使用之前配置的客户端 pusher 实例 。

要在客户端侦听事件,你必须首先订阅发出事件的通道

const channel = pusher.subscribe("my-channel");

然后你可以监听事件

channel.bind("my-event", (data) => {
  // 接收到事件时要分发的方法
});

渠道类型

Masonite 中包含不同的频道类型。

公共频道

在事件类中,你可以指定公共频道。这些频道允许任何有连接的人收听此频道上的事件:

from masonite.broadcasting import Channel

class UserAdded(CanBroadcast):

    def broadcast_on(self):
        return Channel("channel_name")

私有频道

私有频道需要用户授权才能连接到频道。你可以使用此通道仅发出用户应该监听的事件。

私有频道是以 private- 前缀开头的频道。使用私有频道时,会自动为你添加前缀。

私有频道只有在用户登录的情况下才能广播。当频道被授权时,它会在广播之前检查用户当前是否经过身份验证。如果用户未通过身份验证,它将不会在此频道上广播任何内容。

from masonite.broadcasting import PrivateChannel

class UserAdded(CanBroadcast):

    def broadcast_on(self):
      return PrivateChannel("channel_name")

这将在 private-channel_name 频道上发出事件。

路由

在前端,当你连接到私有频道时,广播客户端会触发 POST 请求来验证私有频道。 Masonite 为你提供了此身份验证路径。你需要做的就是将其添加到你的路线中:

from masonite.broadcasting import Broadcast

ROUTES = [
  # 正常的路由列表在这里
]

ROUTES += Broadcast.routes()

这将创建一个路由,你可以在前端验证你的私有频道。授权路线将是 /broadcasting/authorize 但你可以将其更改为你喜欢的任何内容:

ROUTES += Broadcast.routes(auth_route="/pusher/user-auth")

Pusher 期望身份验证路由为 /pusher/user-auth 默认情况下。如果你想改变这个客户端,你可以创建 Pusher 实例时做到。

const pusher = new Pusher("478b45309560f3456211", {
  cluster: "eu",
  userAuthentication: {
    endpoint: "/broadcast/auth",
  },
});

你还需要将 /pusher/user-auth 路由添加到 CSRF 豁免。

class VerifyCsrfToken(Middleware):

    exempt = [
        '/pusher/user-auth'
    ]

原因是广播客户端不会将 CSRF 令牌与 POST 授权请求一起发送。

如果你想保持 CSRF 保护,你可以在 此处 阅读更多相关信息。

授权

默认行为是授权每个人访问任何私有频道。

如果你想自定义频道授权逻辑,你可以使用自定义控制器添加自己的广播授权路由。
假设你要对每个用户的频道进行身份验证,这意味着 ID 为 1 的用户将能够对频道 private-1 进行身份验证,ID 为 2 的用户将能够对频道 private-2 进行身份验证,依此类推。

首先,你需要从你的路线中删除 Broadcast.routes() 并添加你自己的路线

# routes/web.py
Route.post("/pusher/user-auth", "BroadcastController@authorize")

然后你需要创建一个自定义控制器来实现你的逻辑

# app/controllers/BroadcastController.py
from masonite.controllers import Controller
from masonite.broadcasting import Broadcast
from masonite.helpers import optional


class BroadcastController(Controller):

    def authorize(self, request: Request, broadcast: Broadcast):
        channel_name = request.input("channel_name")
        _, user_id = channel_name.split("-")

        if int(user_id) == optional(request.user()).id:
            return broadcast.driver("pusher").authorize(
                channel_name, request.input("socket_id")
            )
        else:
            return False

状态频道

状态频道的工作方式与私有频道完全相同,只是你可以看到该频道内还有谁。这非常适合聊天室类型的应用程序。

对于状态(Presence)频道,用户还必须经过身份验证。

from masonite.broadcasting import PresenceChannel

class UserAdded(CanBroadcast):

    def broadcast_on(self):
      return PresenceChannel("channel_name")

This will emit events on the presence-channel_name channel.

路由

添加认证路由与 私有频道 相同。

授权

授权频道与私有频道相同。

例子

为了更轻松地开始使用 Masonite 中的事件广播,此处提供了两个小示例:

  • 向每个用户发送公共应用发布通知(使用 公共频道
  • 向管理员用户发送私有警报(使用 私有频道

发送公共应用发布通知

为此,我们需要创建一个 NewRelease 广播事件并从后端触发此事件。

# app/broadcasts/NewRelease.py
from masonite.broadcasting import CanBroadcast, Channel

class NewRelease(CanBroadcast):

    def __init__(self, version):
        self.version = version

    def broadcast_on(self):
        return Channel("releases")

    def broadcast_with(self):
        return {"message": f"Version {self.version} has been released !"}
from masonite.facades import Broadcast
from app.broadcasts import NewRelease

Broadcast.channel(NewRelease("4.0.0"))

On the frontend we need to listen to releases channel and subscribe to NewRelease events to display an alert box with the release message.

<html lang="en">
<head>
  <title>Document</title>
  <script src="https://js.pusher.com/7.0/pusher.min.js"></script>
</head>
<body>
  <script>
    const pusher = new Pusher("478b45309560f3456211", {
      cluster: "eu"
    });

    const channel = pusher.subscribe('releases');
    channel.bind('NewRelease', (data) => {
      alert(data.message)
    })
  </script>
</body>
</html>

向管理员用户发送私有警报

Let’s imagine our User model has two roles basic and admin and that we want to send alerts to
admin users only. The basic users should not be authorized to subscribe to the alerts.

假设我们的 User 模型有两个角色 basicadmin 并且我们想要发送警报并仅限发送到管理员用户。基本用户不应提供订阅警报的授权。

为了在后端实现这一点,我们需要:

  • 创建自定义身份验证路由,仅在通道 private-admins 上授权管理员用户
  • 创建一个 AdminUserAlert 广播事件
  • 从后端触发此事件。

让我们首先创建身份验证路由和控制器

# routes/web.py
Route.post("/pusher/user-auth", "BroadcastController@authorize")
# app/controllers/BroadcastController.py
from masonite.controllers import Controller
from masonite.broadcasting import Broadcast
from masonite.helpers import optional


class BroadcastController(Controller):

    def authorize(self, request: Request, broadcast: Broadcast):
        channel_name = request.input("channel_name")
        authorized = True

        # 检查私有管理员频道的权限,否则授权所有其他频道
        if channel_name == "private-admins":
            # 检查用户是否已登录和管理员
            if optional(request.user()).role != "admin":
                authorized = False

        if authorized:
            return broadcast.driver("pusher").authorize(
                channel_name, request.input("socket_id")
            )
        else:
            return False
# app/broadcasts/UserAlert.py
from masonite.broadcasting import CanBroadcast, Channel

class AdminUserAlert(CanBroadcast):

    def __init__(self, message, level="error"):
        self.message = message
        self.level = level

    def broadcast_on(self):
        return Channel("private-admins")

    def broadcast_with(self):
        return {"message": self.message, "level": self.level}
from masonite.facades import Broadcast
from app.broadcasts import AdminUserAlert

Broadcast.channel(AdminUserAlert("Some dependencies are outdated !", level="warning"))

在前端,我们需要监听 private-admins 频道并订阅 AdminUserAlert 事件以显示带有消息的警报框。

<html lang="en">
<head>
  <title>Document</title>
  <script src="https://js.pusher.com/7.0/pusher.min.js"></script>
</head>
<body>
  <script>
    const pusher = new Pusher("478b45309560f3456211", {
      cluster: "eu"
    });

    const channel = pusher.subscribe('private-admins');
    channel.bind('AdminUserAlert', (data) => {
      alert(`[${data.level.toUpperCase()}] ${data.message}`)
    })
  </script>
</body>
</html>

你已准备好开始在你的应用程序中广播事件!

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/masonite/4.0/fe...

译文地址:https://learnku.com/docs/masonite/4.0/fe...

上一篇 下一篇
贡献者:2
讨论数量: 0
发起讨论 只看当前版本


暂无话题~