Взаимодействие между HTTP и веб-сокетами в Django каналах - PullRequest
0 голосов
/ 23 января 2020

У меня есть пользовательский интерфейсный клиент, который обрабатывает HTTP-запросы (webhooks)

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"),])

, и у меня есть внутренний пользовательский интерфейс, который обрабатывает подключения через веб-сокет.

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. Я бы установил sh соединение через websocket
  2. чтобы webhook отправил http-запрос на мой внешний интерфейс.
  3. внешний интерфейс будет отправлять сообщение бэкэнду (через обмен сообщениями по каналам)
  4. внутренний интерфейс будет отправлять сообщение во внешний интерфейс.
  5. конечное сообщение будет заканчиваться sh запрос http.

Но это не работает, шаг 4, с сообщением, возвращающимся в интерфейс, сообщающим, что обработчик отсутствует. Почему это так?

Ответы [ 2 ]

1 голос
/ 24 января 2020

Вы используете одну и ту же группу для разговора в обоих направлениях, это означает, что когда вы отправляете webhook.reg из бэкэнда, она в итоге попытается вызвать функцию webhook_reg для каждого экземпляра backEndConsumer, но такого метода там нет .

Вы должны создать 2 группы.

  • backend_to_frontend
  • frontend_to_backend

  • the frontend должен group_add backend_to_frontend
  • backend должен group_add frontend_to_backend

&

  • в backend Вы должны group_send до backend_to_frontend
  • в frontend Вы должны group_send до frontend_to_backend
0 голосов
/ 26 января 2020

Мне удалось заставить это работать, используя либо два имени группы, либо два имени канала. Кроме того, зная, что http_reponse завершит работу, контекст http_request помог мне отладить, почему я не смог вернуть сообщение в диалоговый поток.

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...