# 2.1.0 Release Notes

Channels 2.1 brings a few new major changes to Channels as well as some more minor fixes. In addition, if you’ve not yet seen it, we now have a long-form tutorial to better introduce some of the concepts and sync versus async styles of coding.

## Major Changes

### Async HTTP Consumer

There is a new native-async HTTP consumer class, `channels.generic.http.AsyncHttpConsumer`. This allows much easier writing of long-poll endpoints or other long-lived HTTP connection handling that benefits from native async support.

You can read more about it in the Consumers documentation.

### WebSocket Consumers

These consumer classes now all have built-in group join and leave functionality, which will make a consumer join all group names that are in the iterable `groups` on the consumer class (this can be a static list or a `@property` method).

In addition, the `accept` methods on both variants now take an optional `subprotocol` argument, which will be sent back to the WebSocket client as the subprotocol the server has selected. The client’s advertised subprotocols can, as always, be found in the scope as `scope["subprotocols"]`.

### Nested URL Routing

`URLRouter` instances can now be nested inside each other and, like Django’s URL handling and `include`, will strip off the matched part of the URL in the outer router and leave only the unmatched portion for the inner router, allowing reusable routing files.

Note that you cannot use the Django `include` function inside of the `URLRouter` as it assumes a bit too much about what it is given as its left-hand side and will terminate your regular expression/URL pattern wrongly.

### Login and Logout

As well as overhauling the internals of the `AuthMiddleware`, there are now also `login` and `logout` async functions you can call in consumers to log users in and out of the current session.

Due to the way cookies are sent back to clients, these come with some caveats; read more about them and how to use them properly in Authentication.

### In-Memory Channel Layer

The in-memory channel layer has been extended to have full expiry and group support so it should now be suitable for drop-in replacement for most test scenarios.

### Testing

The `ChannelsLiveServerTestCase` has been rewritten to use a new method for launching Daphne that should be more resilient (and faster), and now shares code with the Daphne test suite itself.

Ports are now left up to the operating system to decide rather than being picked from within a set range. It also now supports static files when the Django `staticfiles` app is enabled.

In addition, the Communicator classes have gained a `receive_nothing` method that allows you to assert that the application didn’t send anything, rather than writing this yourself using exception handling. See more in the Testing documentation.

### Origin header validation

As well as removing the `print` statements that accidentally got into the last release, this has been overhauled to more correctly match against headers according to the Origin header spec and align with Django’s `ALLOWED_HOSTS` setting.

It can now also enforce protocol (`http` versus `https`) and port, both optionally.

## Bugfixes & Small Changes

- `print` statements that accidentally got left in the `Origin` validation code were removed.

- The `runserver` command now shows the version of Channels you are running.

- Orphaned tasks that may have caused warnings during test runs or occasionally live site traffic are now correctly killed off rather than letting them die later on and print warning messages.

- `WebsocketCommunicator` now accepts a query string passed into the constructor and adds it to the scope rather than just ignoring it.

- Test handlers will correctly handle changing the `CHANNEL_LAYERS` setting via decorators and wipe the internal channel layer cache.

- `SessionMiddleware` can be safely nested inside itself rather than causing a runtime error.

## Backwards Incompatible Changes

- The format taken by the `OriginValidator` for its domains has changed and `*.example.com` is no longer allowed; instead, use `.example.com` to match a domain and all its subdomains.

- If you previously nested `URLRouter` instances inside each other both would have been matching on the full URL before, whereas now they will match on the unmatched portion of the URL, meaning your URL routes would break if you had intended this usage.