Search code examples
djangowebsocketdjango-channels

Django Channels - WebSockets: Cannot find websocket_accept method defined anywhere


Might be a silly one, but I really can't figure this out.

I am going through the source code of Django Channels in order to understand which is the best way to manually terminate an open web socket connection from the server. Then I noticed that the accept method of the WebsocketConsumer sends a message of type websocket.accept: https://github.com/django/channels/blob/master/channels/generic/websocket.py#L52

According to Django Channel docs, that means there is somewhere a method named websocket_accept that will be invoked on the consumer:

Consumers are structured around a series of named methods corresponding to the type value of the messages they are going to receive, with any . replaced by _.

But I cannot find a websocket_accept method anywhere in the repository (I even cloned it and grep'ed to it).

Same goes for websocket_close: https://github.com/django/channels/blob/master/channels/generic/websocket.py#L88. Where is it defined?

So I am wondering how does this work. Have I interpreted wrong or the docs mean something different (eg. some other method should be called instead of the one(s) I think they will)?

Thanks


Solution

  • The consumer handlers are divided into protocol handlers (the ones with websocket preprended for the websocket consumer like websocket_disconnect, etc) and instance level handlers (the ones without websocket preprended like disconnect).

    The protocol handlers usually handle requests sent from outside the consumer instance, via the channel layer. It could be sent from a downstream consumer to an upstream consumer and if not handled by the current consumer is sent further upstream up till the websocket server.

    Since the ASGI protocol is "Turtles all the way down", all the consumers up to the websocket protocol servers behave alike and have similar handlers implemented.

    In essence, you did not see the websocket_accept handler because no generic consumer in channels handles it and hence, it will be handled by the websocket server you are using. This particular event is what triggers the upgrade of the connection from HTTP to websocket and this is done by the websocket server. Similarly for websocket_close, it is sent upstream where the websocket server handles it by closing the websocket connection. You can find more about the handlers defined in the ASGI protocol here

    Note that if you have child consumers that depend on a parent consumer (like in the case of the Demultiplexer implemented here), then you can have those protocol handlers like websocket_accept but must ensure you send it further upstream to the websocket server, else it will not be handled properly and the connection will not be upgraded