Channels: Unable to route a consumer through an included path

Created on 5 May 2017  路  7Comments  路  Source: django/channels

I鈥檓 attempting to route a channel to a consumer to handle messages from both javascript and model changes via a post_save signal. This works when I includethe routes without a path, but including WITH the path produces an error:

ERROR - worker - Could not find match for message on consumer! Check your routing

The error occurs on socket connection since I鈥檓 sending a message on connect from my javascript and also appears when I attempt to save my model.

It appears that something within the includefunctionality is preventing Channelrouting if a path is provided. Either that or the documentation failed to mention how to properly set up channels to handle paths within the routes.

// javascript call

socket = new WebSocket("ws://" + window.location.host + "/mission");
socket.onmessage = function(e) {
    alert(e.data);
}
socket.onopen = function() {
    socket.send("hello world");
}
// Call onopen directly if socket is already open
if (socket.readyState == WebSocket.OPEN) socket.onopen();
# routing.py 

from channels.routing import route, include
from vits.consumers import ws_connect, ws_message, ws_disconnect, msg_consumer

mission_routing = [
    route("websocket.connect", ws_connect),
    route("websocket.receive", ws_message),
    route("websocket.disconnect", ws_disconnect),
    route("consumer", msg_consumer),
]

routing = [
  include(mission_routing, path=r"^/mission") # note: this is where the path is declared. Without path declaration routing works as expected, with path error from above is produced
]
# In consumers.py
from channels import Channel
from channels.sessions import channel_session
from channels import Group


# Connected to chat-messages
def msg_consumer(message):
  print("Message Consumed")
  Group("mission_listeners").send({
    "text": message.content['message']
  })

# Connected to websocket.connect
@channel_session
def ws_connect(message):
    print("ws_connect")
    # Work out room name from path (ignore slashes)
    room = message.content['path'].strip("/")
    # Save room in session and add us to the group
    message.channel_session['room'] = room
    Group("mission_listeners").add(message.reply_channel)
    # Accept the connection request
    message.reply_channel.send({"accept": True})

# Connected to websocket.receive
@channel_session
def ws_message(message):
    # Stick the message onto the processing queue
    print(message['text'])
    Channel("consumer").send({
        "message": message['text'],
    })

# Connected to websocket.disconnect
@channel_session
def ws_disconnect(message):
    Group("mission_listeners").discard(message.reply_channel)
blockeuser-response

Most helpful comment

It's somewhat covered here: http://channels.readthedocs.io/en/latest/getting-started.html#routing

I will say we could probably specifically call this out, however. You're not the first person to make this mistake by far.

All 7 comments

Does it work if you add the path individually to the routes rather than on the include?

It does not actually. So the error isn't limited to the include functionality as I originally surmised. Or I'm still doing something wrong :/

mission_routing = [
    route("websocket.connect", ws_connect, path=r"^/mission"),
    route("websocket.receive", ws_message),
    route("websocket.disconnect", ws_disconnect),
    route("consumer", msg_consumer, path=r"^/mission"),
]

Hm, are you complaining that the consumer channel one isn't working? Where are messages for that coming from?

From both javascript and model changes via a post_save signal. When I attempt to route any of my messages through the consumer via

Channel("consumer").send({
         "message": message['text'],
     })

I get the error:

ERROR - worker - Could not find match for message on consumer! Check your routing

Ah, well that's because you don't have a path key in your message - the routing isn't magical, it just goes off of the contents of the message. websocket.connect and websocket.receive messages include a path key so they can be routed, whereas yours just has a message key.

Given you have made a separate channel especially for this, there's no need for the path routing unless you really want to distinguish it, in which case you should ensure a path is added to the message when it's sent onto the channel.

Ah. That would explain it then. Much obliged.

Is this documented somewhere that I can go and review or would I have needed to dive into the code base itself to figure out that the message required a path key?

It's somewhat covered here: http://channels.readthedocs.io/en/latest/getting-started.html#routing

I will say we could probably specifically call this out, however. You're not the first person to make this mistake by far.

Was this page helpful?
0 / 5 - 0 ratings