<commit_before>================
django-websocket
================

The **django-websocket** module provides an implementation of the WebSocket
Protocol for django. It handles all the low-level details like establishing
the connection through sending handshake reply, parsing messages from the
browser etc...

It integrates well into django since it provides easy hooks to receive
WebSocket requests either for single views through decorators or for the whole
site through a custom middleware.

Usage
=====

You can use the ``accept_websocket`` decorator if you want to handle websocket
connections just for a single view - it will route standard HTTP requests to
the view as well. Use ``require_websocket`` to only allow WebSocket
connections but reject normal HTTP requests.

You can use a middleware if you want to have WebSockets available for *all*
URLs in your application. Add
``django_websocket.middleware.WebSocketMiddleware`` to your
``MIDDLEWARE_CLASSES`` setting. This will still reject websockets for normal
views. You have to set the ``accept_websocket`` attribute on a view to allow
websockets.

To allow websockets for *every single view*, set the ``WEBSOCKET_ACCEPT_ALL``
setting to ``True``.

The request objects passed to a view, decorated with ``accept_websocket`` or
``require_websocket`` will have the following attributes/methods attached.
These attributes are always available if you use the middleware.

``request.is_websocket()``
--------------------------

Returns either ``True`` if the request has a valid websocket or ``False`` if
its a normal HTTP request. Use this method in views that can accept both types
of requests to distinguish between them.

``request.websocket``
---------------------

After a websocket is established, the request will have a ``websocket``
attribute which provides a simple API to communicate with the client. This
attribute will be ``None`` if ``request.is_websocket()`` returns ``False``.

It has the following public methods:

``WebSocket.wait()``
~~~~~~~~~~~~~~~~~~~~

This will return exactly one message sent by the client. It will not return
before a message is received or the conection is closed by the client. In this
case the method will return ``None``.

``WebSocket.read()``
~~~~~~~~~~~~~~~~~~~~

The ``read`` method will return either a new message if available or ``None``
if no new message was received from the client. It is a non-blocking
alternative to the ``wait()`` method.

``WebSocket.count_messages()``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Returns the number of queued messages.

``WebSocket.has_messages()``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Returns ``True`` if new messages are available, else ``False``.

``WebSocket.send(message)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~

This will send a single message to the client.

``WebSocket.__iter__()``
~~~~~~~~~~~~~~~~~~~~~~~~

You can use the websocket as iterator. It will yield every new message sent by
the client and stop iteration after the client has closed the connection.

Error handling
--------------

The library will return a Http 400 error (Bad Request) if the client requests
a WebSocket connection, but the request is malformed or not supported by
*django-websocket*.

Examples
========

Receive one message from the client, send that message back to the client and
close the connection (by returning from the view)::

    from django_websocket import require_websocket

    @require_websocket
    def echo_once(request):
        message = request.websocket.wait()
        request.websocket.send(message)

Send websocket messages from the client as lowercase and provide same
functionallity for normal GET requests::

    from django.http import HttpResponse
    from django_websocket import accept_websocket

    def modify_message(message):
        return message.lower()

    @accept_websocket
    def lower_case(request):
        if not request.is_websocket():
            message = request.GET['message']
            message = modify_message(message)
            return HttpResponse(message)
        else:
            for message in request.websocket:
                message = modify_message(message)
                request.websocket.send(message)

Disclaimer (what you should know when using django-websocket)
=============================================================

Using in development
--------------------

Django doesn't support a multithreaded development server yet. It is still not
possible to open two concurrent requests. This makes working with WebSockets a
bit tedious - since WebSockets will require an open request by their nature.

This has the implication that you won't be able to have more than one
WebSocket open at a time when using django's ``runserver`` command. It's also
not possible to fire an AJAX request while a WebSocket is in use etc.

**django-websocket** ships with a custom ``runserver`` command that works
around these limitations. Add ``django_websocket`` to your ``INSTALLED_APPS``
settings to install it. Use your development server like you did before and
provide the ``--multithreaded`` option to enable multithreaded behaviour::

    python manage.py runserver --multithreaded

Using in production
-------------------
<commit_msg>Adding big fat disclaimer about using websockets with WSGI and django.<commit_after>================
django-websocket
================

**IMPORTANT: Please read the disclaimer a few sections below before you start
using django-websocket.**

The **django-websocket** module provides an implementation of the WebSocket
Protocol for django. It handles all the low-level details like establishing
the connection through sending handshake reply, parsing messages from the
browser etc...

It integrates well into django since it provides easy hooks to receive
WebSocket requests either for single views through decorators or for the whole
site through a custom middleware.

Usage
=====

You can use the ``accept_websocket`` decorator if you want to handle websocket
connections just for a single view - it will route standard HTTP requests to
the view as well. Use ``require_websocket`` to only allow WebSocket
connections but reject normal HTTP requests.

You can use a middleware if you want to have WebSockets available for *all*
URLs in your application. Add
``django_websocket.middleware.WebSocketMiddleware`` to your
``MIDDLEWARE_CLASSES`` setting. This will still reject websockets for normal
views. You have to set the ``accept_websocket`` attribute on a view to allow
websockets.

To allow websockets for *every single view*, set the ``WEBSOCKET_ACCEPT_ALL``
setting to ``True``.

The request objects passed to a view, decorated with ``accept_websocket`` or
``require_websocket`` will have the following attributes/methods attached.
These attributes are always available if you use the middleware.

``request.is_websocket()``
--------------------------

Returns either ``True`` if the request has a valid websocket or ``False`` if
its a normal HTTP request. Use this method in views that can accept both types
of requests to distinguish between them.

``request.websocket``
---------------------

After a websocket is established, the request will have a ``websocket``
attribute which provides a simple API to communicate with the client. This
attribute will be ``None`` if ``request.is_websocket()`` returns ``False``.

It has the following public methods:

``WebSocket.wait()``
~~~~~~~~~~~~~~~~~~~~

This will return exactly one message sent by the client. It will not return
before a message is received or the conection is closed by the client. In this
case the method will return ``None``.

``WebSocket.read()``
~~~~~~~~~~~~~~~~~~~~

The ``read`` method will return either a new message if available or ``None``
if no new message was received from the client. It is a non-blocking
alternative to the ``wait()`` method.

``WebSocket.count_messages()``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Returns the number of queued messages.

``WebSocket.has_messages()``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Returns ``True`` if new messages are available, else ``False``.

``WebSocket.send(message)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~

This will send a single message to the client.

``WebSocket.__iter__()``
~~~~~~~~~~~~~~~~~~~~~~~~

You can use the websocket as iterator. It will yield every new message sent by
the client and stop iteration after the client has closed the connection.

Error handling
--------------

The library will return a Http 400 error (Bad Request) if the client requests
a WebSocket connection, but the request is malformed or not supported by
*django-websocket*.

Examples
========

Receive one message from the client, send that message back to the client and
close the connection (by returning from the view)::

    from django_websocket import require_websocket

    @require_websocket
    def echo_once(request):
        message = request.websocket.wait()
        request.websocket.send(message)

Send websocket messages from the client as lowercase and provide same
functionallity for normal GET requests::

    from django.http import HttpResponse
    from django_websocket import accept_websocket

    def modify_message(message):
        return message.lower()

    @accept_websocket
    def lower_case(request):
        if not request.is_websocket():
            message = request.GET['message']
            message = modify_message(message)
            return HttpResponse(message)
        else:
            for message in request.websocket:
                message = modify_message(message)
                request.websocket.send(message)

Disclaimer (what you should know when using django-websocket)
=============================================================

**BIG FAT DISCLAIMER** - right at the moment its technically *NOT* possible in
any way to use a websocket with WSGI. This is a known issue but cannot be
worked around in a clean way due to some design decision that were made while
the WSGI stadard was written. At this time things like Websockets etc. didn't
exist and were not predictable.

However there are thoughts to extend the WSGI standard to make Websockets
possible. `Read here for a discussion on the Paste Users mailing list
<http://groups.google.com/group/paste-users/browse_thread/thread/2f3a5ba33b857c6c>`_.

But not only WSGI is the limiting factor. Django itself was designed around a
simple request to response scenario without Websockets in mind. This also
means that providing a standard conform websocket implemention is not possible
right now for django. However it works somehow in a not-so pretty way. So be
aware that tcp sockets might get tortured while using django-websocket.

Using in development
--------------------

Django doesn't support a multithreaded development server yet. It is still not
possible to open two concurrent requests. This makes working with WebSockets a
bit tedious - since WebSockets will require an open request by their nature.

This has the implication that you won't be able to have more than one
WebSocket open at a time when using django's ``runserver`` command. It's also
not possible to fire an AJAX request while a WebSocket is in use etc.

**django-websocket** ships with a custom ``runserver`` command that works
around these limitations. Add ``django_websocket`` to your ``INSTALLED_APPS``
settings to install it. Use your development server like you did before and
provide the ``--multithreaded`` option to enable multithreaded behaviour::

    python manage.py runserver --multithreaded

Using in production
-------------------

{'fraction_non_alphanumeric': 0.1184530003468609, 'fraction_numerical': 0.0013007284079084287, 'mean_word_length': 4.139483065953654, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3562996', 'n_tokens_mistral': 2896, 'n_tokens_neox': 2731, 'n_words': 1430}