【问题标题】:Interactions between HTTP and websocket connections in Django ChannelsDjango Channels 中 HTTP 和 websocket 连接之间的交互
【发布时间】:2020-01-23 20:17:41
【问题描述】:

我有一个处理 HTTP 请求(webhook)的前端消费者

from django.views.decorators.csrf import csrf_exempt
from channels.generic.http import AsyncHttpConsumer
from django.http import JsonResponse
import json
import myapp.models
import redis

@csrf_exempt 
class frontEndConsumer(AsyncHttpConsumer):

    async def http_request(self, request):

        await self.channel_layer.group_add("link", self.channel_name)
        await self.channel_layer.group_send("link",
            {
               "type": "websocket.reg",
               "where": "webhook",
               "message": "test message",
            })

#channel layer functions
    async def webhook_reg(self, event):
        print("WH: message from " + event["where"] + ": " + event["message"]
        # make response
        fulfillmentText = "device connected"
        fulfillmentText = {'fulfillmentText': fulfillmentText}
        fulfillmentText = json.dumps(fulfillmentText).encode('utf-8') 
        await self.send_response(200, fulfillmentText, 
            headers=[(b"Content-Type", b"text/plain"),])

我有一个处理 websocket 连接的后端消费者。

from channels.generic.websocket import AsyncJsonWebsocketConsumer
import redis
import myapp.models
account = redis.Redis(db=0)

class backEndConsumer(AsyncJsonWebsocketConsumer):

    async def websocket_connect(self, type):
        await self.channel_layer.group_add("link", self.channel_name)
        print("channel name: " + self.channel_name)
        await self.accept()

#channel layer functions 
    async def websocket_reg(self, event):
        print("WS: message from " + event["where"] + ": " + event["message"])

        await self.channel_layer.group_send("link",
            {
               "type": "webhook.reg",
               "where": "websocket",
               "message": "msg from websocket",
            })
        await self.send(event["message"])

我在 procfile 中启动它们:

web: daphne APbackend.asgi:application --port $PORT --bind 0.0.0.0

我正在使用 django 频道让前台和后台相互交谈。在我的代码中,我试图让双方互相发送消息。

  1. 我会建立 websocket 连接
  2. 让 webhook 向我的前端发送一个 http 请求。
  3. 前端会向后端发送消息(通过通道消息传递)
  4. 后端会向前端发送消息。
  5. 前端消息将完成 http 请求。

但这不起作用,第 4 步,消息返回到前端,说处理程序丢失。这是为什么呢?

【问题讨论】:

  • csrf_exempt 我不认为你可以在 AsyncHttpConsumer 消费者上使用它。你能分享一下你是如何配置你的 ASGI 应用程序的吗?您如何使用frontEndConsumerbackEndConsumer
  • application = ProtocolTypeRouter({ "websocket": URLRouter([ path('ws/', backEndConsumer), ]), "http": URLRouter([ path('webhook/', frontEndConsumer), ]),是我配置 asgi 应用程序的方式。http 路由到前端,websocket 路由到后端。我可能会添加一个网页,所以我使用 URLrouter 将其拆分。csrf_exempt 是我因为教程而放入的。我是不确定它的作用细节,或者它是否适用于我。
  • csrf_exempt 在频道中无效。

标签: django django-channels


【解决方案1】:

您使用同一个组进行双向通话,这意味着当您从后端发送webhook.reg 时,它最终会尝试在每个backEndConsumer 实例上调用函数webhook_reg,但那里没有这样的方法.

您应该创建 2 个组。

  • backend_to_frontend
  • frontend_to_backend

  • frontend应该group_addbackend_to_frontend
  • backend 应该是group_add frontend_to_backend

&

  • backend 你应该group_sendbackend_to_frontend
  • frontend 你应该group_sendfrontend_to_backend

【讨论】:

  • 如果我发送响应,知道 http_requests 会结束它的上下文,这肯定有助于我弄清楚我做错了什么。结果证明我的设计不需要 group_send 的广播功能,只需要频道名称!
【解决方案2】:

我可以使用两个组名或两个频道名来完成这项工作。还知道 http_reponse 会结束 http_request 上下文有助于我调试为什么我无法将消息返回到对话流。

谢谢!

【讨论】:

    猜你喜欢
    • 2022-01-12
    • 2021-07-03
    • 2019-05-03
    • 2021-03-07
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 2020-06-26
    • 2019-02-26
    相关资源
    最近更新 更多