From 79927fbe1065c6a2d2ed1c7b265edbc33c155f74 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 29 Jul 2017 03:42:50 +0100 Subject: [PATCH 01/11] Travis - test on Trusty (#129) As per [their blog post](https://blog.travis-ci.com/2017-07-11-trusty-as-default-linux-is-coming) they're making it the new default, best to be ahead of the curve. --- .travis.yml | 1 + daphne/tests/__init__.py | 7 +++++++ daphne/tests/test_http_request.py | 3 +-- daphne/tests/test_http_response.py | 3 +-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9672140..da96f02 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ sudo: false +dist: trusty language: python diff --git a/daphne/tests/__init__.py b/daphne/tests/__init__.py index e69de29..3f43747 100644 --- a/daphne/tests/__init__.py +++ b/daphne/tests/__init__.py @@ -0,0 +1,7 @@ +from hypothesis import HealthCheck, settings + +settings.register_profile( + 'daphne', + settings(suppress_health_check=[HealthCheck.too_slow]), +) +settings.load_profile('daphne') diff --git a/daphne/tests/test_http_request.py b/daphne/tests/test_http_request.py index ee38ab9..ef7922d 100644 --- a/daphne/tests/test_http_request.py +++ b/daphne/tests/test_http_request.py @@ -8,7 +8,7 @@ import unittest from six.moves.urllib import parse from asgiref.inmemory import ChannelLayer -from hypothesis import given, assume, settings, HealthCheck +from hypothesis import given, assume from twisted.test import proto_helpers from daphne.http_protocol import HTTPFactory @@ -99,7 +99,6 @@ class TestHTTPRequestSpec(testcases.ASGIHTTPTestCase): request_body=http_strategies.http_body(), ) # This test is slow enough that on Travis, hypothesis sometimes complains. - @settings(suppress_health_check=[HealthCheck.too_slow]) def test_kitchen_sink( self, request_method, request_path, request_params, request_headers, request_body): """ diff --git a/daphne/tests/test_http_response.py b/daphne/tests/test_http_response.py index 1ee27b1..f5f5a28 100644 --- a/daphne/tests/test_http_response.py +++ b/daphne/tests/test_http_response.py @@ -7,7 +7,7 @@ from __future__ import unicode_literals from unittest import TestCase from asgiref.inmemory import ChannelLayer -from hypothesis import given, settings +from hypothesis import given from twisted.test import proto_helpers from daphne.http_protocol import HTTPFactory @@ -72,7 +72,6 @@ class TestHTTPResponseSpec(testcases.ASGIHTTPTestCase): headers=http_strategies.headers(), body=http_strategies.http_body(), ) - @settings(perform_health_check=False) def test_kitchen_sink(self, headers, body): """ This tests tries to let Hypothesis find combinations of variables that result From a69d69490bfb1a101e6c923f785e2438666e4a53 Mon Sep 17 00:00:00 2001 From: Tom Turner Date: Sun, 30 Jul 2017 11:28:08 +0100 Subject: [PATCH 02/11] Removed a unsed import (urlencode) (#131) --- daphne/ws_protocol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daphne/ws_protocol.py b/daphne/ws_protocol.py index 502f340..a432285 100755 --- a/daphne/ws_protocol.py +++ b/daphne/ws_protocol.py @@ -4,7 +4,7 @@ import logging import six import time import traceback -from six.moves.urllib_parse import unquote, urlencode +from six.moves.urllib_parse import unquote from twisted.internet import defer from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory, ConnectionDeny From 3161715238c2dea9424c39f327a1f152c98a3cac Mon Sep 17 00:00:00 2001 From: Artem Malyshev Date: Sun, 13 Aug 2017 19:18:54 +0300 Subject: [PATCH 03/11] Log interface listener errors. Fix #133. --- daphne/server.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/daphne/server.py b/daphne/server.py index 9340524..0ae9eda 100755 --- a/daphne/server.py +++ b/daphne/server.py @@ -121,10 +121,19 @@ class Server(object): logger.info("Listening on endpoint %s" % socket_description) # Twisted requires str on python2 (not unicode) and str on python3 (not bytes) ep = serverFromString(reactor, str(socket_description)) - self.listeners.append(ep.listen(self.factory)) + listener = ep.listen(self.factory) + listener.addErrback(self.on_listener_error) + self.listeners.append(listener) reactor.run(installSignalHandlers=self.signal_handlers) + def on_listener_error(self, failure): + """ + Callback function used to process interface listener errors. + """ + + logger.error(failure.getErrorMessage()) + def backend_reader_sync(self): """ Runs as an-often-as-possible task with the reactor, unless there was From 05bd4ac258ee4d3fa1a9d2c6096df44b28810721 Mon Sep 17 00:00:00 2001 From: Nick Sellen Date: Fri, 25 Aug 2017 18:24:24 +0100 Subject: [PATCH 04/11] Parse X-Forwarded-Proto header (#136) Adds the ability to use this header for HTTPS detection. --- daphne/cli.py | 1 + daphne/http_protocol.py | 10 ++++-- daphne/server.py | 3 ++ daphne/tests/test_http_request.py | 2 ++ daphne/tests/test_utils.py | 59 ++++++++++++++++++++++--------- daphne/utils.py | 26 +++++++++----- daphne/ws_protocol.py | 3 +- 7 files changed, 75 insertions(+), 29 deletions(-) diff --git a/daphne/cli.py b/daphne/cli.py index b27cb06..a149632 100755 --- a/daphne/cli.py +++ b/daphne/cli.py @@ -213,6 +213,7 @@ class CommandLineInterface(object): verbosity=args.verbosity, proxy_forwarded_address_header='X-Forwarded-For' if args.proxy_headers else None, proxy_forwarded_port_header='X-Forwarded-Port' if args.proxy_headers else None, + proxy_forwarded_proto_header='X-Forwarded-Proto' if args.proxy_headers else None, force_sync=args.force_sync, ) self.server.run() diff --git a/daphne/http_protocol.py b/daphne/http_protocol.py index 32dc276..df9f93a 100755 --- a/daphne/http_protocol.py +++ b/daphne/http_protocol.py @@ -80,12 +80,16 @@ class WebRequest(http.Request): self.client_addr = None self.server_addr = None + self.client_scheme = 'https' if self.isSecure() else 'http' + if self.factory.proxy_forwarded_address_header: - self.client_addr = parse_x_forwarded_for( + self.client_addr, self.client_scheme = parse_x_forwarded_for( self.requestHeaders, self.factory.proxy_forwarded_address_header, self.factory.proxy_forwarded_port_header, - self.client_addr + self.factory.proxy_forwarded_proto_header, + self.client_addr, + self.client_scheme ) # Check for unicodeish path (or it'll crash when trying to parse) @@ -166,7 +170,7 @@ class WebRequest(http.Request): "method": self.method.decode("ascii"), "path": self.unquote(self.path), "root_path": self.root_path, - "scheme": "https" if self.isSecure() else "http", + "scheme": self.client_scheme, "query_string": self.query_string, "headers": self.clean_headers, "body": self.content.read(), diff --git a/daphne/server.py b/daphne/server.py index 0ae9eda..fc9f761 100755 --- a/daphne/server.py +++ b/daphne/server.py @@ -36,6 +36,7 @@ class Server(object): root_path="", proxy_forwarded_address_header=None, proxy_forwarded_port_header=None, + proxy_forwarded_proto_header=None, force_sync=False, verbosity=1, websocket_handshake_timeout=5 @@ -66,6 +67,7 @@ class Server(object): self.ping_timeout = ping_timeout self.proxy_forwarded_address_header = proxy_forwarded_address_header self.proxy_forwarded_port_header = proxy_forwarded_port_header + self.proxy_forwarded_proto_header = proxy_forwarded_proto_header # If they did not provide a websocket timeout, default it to the # channel layer's group_expiry value if present, or one day if not. self.websocket_timeout = websocket_timeout or getattr(channel_layer, "group_expiry", 86400) @@ -95,6 +97,7 @@ class Server(object): root_path=self.root_path, proxy_forwarded_address_header=self.proxy_forwarded_address_header, proxy_forwarded_port_header=self.proxy_forwarded_port_header, + proxy_forwarded_proto_header=self.proxy_forwarded_proto_header, websocket_handshake_timeout=self.websocket_handshake_timeout ) if self.verbosity <= 1: diff --git a/daphne/tests/test_http_request.py b/daphne/tests/test_http_request.py index ef7922d..dd64ae3 100644 --- a/daphne/tests/test_http_request.py +++ b/daphne/tests/test_http_request.py @@ -171,6 +171,7 @@ class TestProxyHandling(unittest.TestCase): def test_x_forwarded_for_parsed(self): self.factory.proxy_forwarded_address_header = 'X-Forwarded-For' self.factory.proxy_forwarded_port_header = 'X-Forwarded-Port' + self.factory.proxy_forwarded_proto_header = 'X-Forwarded-Proto' self.proto.dataReceived( b"GET /te%20st-%C3%A0/?foo=+bar HTTP/1.1\r\n" + b"Host: somewhere.com\r\n" + @@ -185,6 +186,7 @@ class TestProxyHandling(unittest.TestCase): def test_x_forwarded_for_port_missing(self): self.factory.proxy_forwarded_address_header = 'X-Forwarded-For' self.factory.proxy_forwarded_port_header = 'X-Forwarded-Port' + self.factory.proxy_forwarded_proto_header = 'X-Forwarded-Proto' self.proto.dataReceived( b"GET /te%20st-%C3%A0/?foo=+bar HTTP/1.1\r\n" + b"Host: somewhere.com\r\n" + diff --git a/daphne/tests/test_utils.py b/daphne/tests/test_utils.py index 525fec9..9e962a6 100644 --- a/daphne/tests/test_utils.py +++ b/daphne/tests/test_utils.py @@ -16,11 +16,13 @@ class TestXForwardedForHttpParsing(TestCase): def test_basic(self): headers = Headers({ b'X-Forwarded-For': [b'10.1.2.3'], - b'X-Forwarded-Port': [b'1234'] + b'X-Forwarded-Port': [b'1234'], + b'X-Forwarded-Proto': [b'https'] }) result = parse_x_forwarded_for(headers) - self.assertEqual(result, ['10.1.2.3', 1234]) - self.assertIsInstance(result[0], six.text_type) + self.assertEqual(result, (['10.1.2.3', 1234], 'https')) + self.assertIsInstance(result[0][0], six.text_type) + self.assertIsInstance(result[1], six.text_type) def test_address_only(self): headers = Headers({ @@ -28,7 +30,7 @@ class TestXForwardedForHttpParsing(TestCase): }) self.assertEqual( parse_x_forwarded_for(headers), - ['10.1.2.3', 0] + (['10.1.2.3', 0], None) ) def test_v6_address(self): @@ -37,7 +39,7 @@ class TestXForwardedForHttpParsing(TestCase): }) self.assertEqual( parse_x_forwarded_for(headers), - ['1043::a321:0001', 0] + (['1043::a321:0001', 0], None) ) def test_multiple_proxys(self): @@ -46,19 +48,39 @@ class TestXForwardedForHttpParsing(TestCase): }) self.assertEqual( parse_x_forwarded_for(headers), - ['10.1.2.3', 0] + (['10.1.2.3', 0], None) ) - def test_original(self): + def test_original_addr(self): headers = Headers({}) self.assertEqual( - parse_x_forwarded_for(headers, original=['127.0.0.1', 80]), - ['127.0.0.1', 80] + parse_x_forwarded_for(headers, original_addr=['127.0.0.1', 80]), + (['127.0.0.1', 80], None) + ) + + def test_original_proto(self): + headers = Headers({}) + self.assertEqual( + parse_x_forwarded_for(headers, original_scheme='http'), + (None, 'http') ) def test_no_original(self): headers = Headers({}) - self.assertIsNone(parse_x_forwarded_for(headers)) + self.assertEqual( + parse_x_forwarded_for(headers), + (None, None) + ) + + def test_address_and_proto(self): + headers = Headers({ + b'X-Forwarded-For': [b'10.1.2.3'], + b'X-Forwarded-Proto': [b'https'], + }) + self.assertEqual( + parse_x_forwarded_for(headers), + (['10.1.2.3', 0], 'https') + ) class TestXForwardedForWsParsing(TestCase): @@ -73,7 +95,7 @@ class TestXForwardedForWsParsing(TestCase): } self.assertEqual( parse_x_forwarded_for(headers), - ['10.1.2.3', 1234] + (['10.1.2.3', 1234], None) ) def test_address_only(self): @@ -82,7 +104,7 @@ class TestXForwardedForWsParsing(TestCase): } self.assertEqual( parse_x_forwarded_for(headers), - ['10.1.2.3', 0] + (['10.1.2.3', 0], None) ) def test_v6_address(self): @@ -91,7 +113,7 @@ class TestXForwardedForWsParsing(TestCase): } self.assertEqual( parse_x_forwarded_for(headers), - ['1043::a321:0001', 0] + (['1043::a321:0001', 0], None) ) def test_multiple_proxys(self): @@ -100,16 +122,19 @@ class TestXForwardedForWsParsing(TestCase): } self.assertEqual( parse_x_forwarded_for(headers), - ['10.1.2.3', 0] + (['10.1.2.3', 0], None) ) def test_original(self): headers = {} self.assertEqual( - parse_x_forwarded_for(headers, original=['127.0.0.1', 80]), - ['127.0.0.1', 80] + parse_x_forwarded_for(headers, original_addr=['127.0.0.1', 80]), + (['127.0.0.1', 80], None) ) def test_no_original(self): headers = {} - self.assertIsNone(parse_x_forwarded_for(headers)) + self.assertEqual( + parse_x_forwarded_for(headers), + (None, None) + ) diff --git a/daphne/utils.py b/daphne/utils.py index cb8043c..95ed331 100644 --- a/daphne/utils.py +++ b/daphne/utils.py @@ -11,18 +11,22 @@ def header_value(headers, header_name): def parse_x_forwarded_for(headers, address_header_name='X-Forwarded-For', port_header_name='X-Forwarded-Port', - original=None): + proto_header_name='X-Forwarded-Proto', + original_addr=None, + original_scheme=None): """ Parses an X-Forwarded-For header and returns a host/port pair as a list. @param headers: The twisted-style object containing a request's headers @param address_header_name: The name of the expected host header @param port_header_name: The name of the expected port header - @param original: A host/port pair that should be returned if the headers are not in the request - @return: A list containing a host (string) as the first entry and a port (int) as the second. + @param proto_header_name: The name of the expected protocol header + @param original_addr: A host/port pair that should be returned if the headers are not in the request + @param original_scheme: A scheme that should be returned if the headers are not in the request + @return: A tuple containing a list [host (string), port (int)] as the first entry and a proto (string) as the second """ if not address_header_name: - return original + return (original_addr, original_scheme) # Convert twisted-style headers into dicts if isinstance(headers, Headers): @@ -32,14 +36,15 @@ def parse_x_forwarded_for(headers, headers = {name.lower(): values for name, values in headers.items()} address_header_name = address_header_name.lower().encode("utf-8") - result = original + result_addr = original_addr + result_scheme = original_scheme if address_header_name in headers: address_value = header_value(headers, address_header_name) if ',' in address_value: address_value = address_value.split(",")[0].strip() - result = [address_value, 0] + result_addr = [address_value, 0] if port_header_name: # We only want to parse the X-Forwarded-Port header if we also parsed the X-Forwarded-For @@ -48,8 +53,13 @@ def parse_x_forwarded_for(headers, if port_header_name in headers: port_value = header_value(headers, port_header_name) try: - result[1] = int(port_value) + result_addr[1] = int(port_value) except ValueError: pass - return result + if proto_header_name: + proto_header_name = proto_header_name.lower().encode("utf-8") + if proto_header_name in headers: + result_scheme = header_value(headers, proto_header_name) + + return result_addr, result_scheme diff --git a/daphne/ws_protocol.py b/daphne/ws_protocol.py index a432285..08f818b 100755 --- a/daphne/ws_protocol.py +++ b/daphne/ws_protocol.py @@ -57,10 +57,11 @@ class WebSocketProtocol(WebSocketServerProtocol): self.server_addr = None if self.main_factory.proxy_forwarded_address_header: - self.client_addr = parse_x_forwarded_for( + self.client_addr, = parse_x_forwarded_for( self.http_headers, self.main_factory.proxy_forwarded_address_header, self.main_factory.proxy_forwarded_port_header, + self.main_factory.proxy_forwarded_proto_header, self.client_addr ) From d24fd06460ac61fd92933b3b7c6aa63ed78ac65c Mon Sep 17 00:00:00 2001 From: Buky <18658299+Buky77@users.noreply.github.com> Date: Tue, 12 Sep 2017 19:22:14 +0200 Subject: [PATCH 05/11] Update Readme.rst (#138) Fix line commande for pip --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index bab5110..aa285b6 100644 --- a/README.rst +++ b/README.rst @@ -57,7 +57,7 @@ Daphne 1.1 and above supports terminating HTTP/2 connections natively. You'll need to do a couple of things to get it working, though. First, you need to make sure you install the Twisted ``http2`` and ``tls`` extras:: - pip install -U Twisted[tls,http2] + pip install -U 'Twisted[tls,http2]' Next, because all current browsers only support HTTP/2 when using TLS, you will need to start Daphne with TLS turned on, which can be done using the Twisted endpoint syntax:: From f9233d4b47eecb55ffe5941914fea58bdeaf2f1d Mon Sep 17 00:00:00 2001 From: Thomas Steen Rasmussen Date: Thu, 12 Oct 2017 20:06:18 +0200 Subject: [PATCH 06/11] Make sure headers are always correctly encoded WebSocket headers were not correctly encoding as bytestrings. --- daphne/utils.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/daphne/utils.py b/daphne/utils.py index 95ed331..04cef09 100644 --- a/daphne/utils.py +++ b/daphne/utils.py @@ -5,7 +5,10 @@ def header_value(headers, header_name): value = headers[header_name] if isinstance(value, list): value = value[0] - return value.decode("utf-8") + # decode to urf-8 if value is bytes + if isinstance(value, bytes): + value = value.decode("utf-8") + return value def parse_x_forwarded_for(headers, @@ -28,12 +31,14 @@ def parse_x_forwarded_for(headers, if not address_header_name: return (original_addr, original_scheme) - # Convert twisted-style headers into dicts if isinstance(headers, Headers): + # Convert twisted-style headers into a dict headers = dict(headers.getAllRawHeaders()) - - # Lowercase all header names in the dict - headers = {name.lower(): values for name, values in headers.items()} + # Lowercase all header keys + headers = {name.lower(): values for name, values in headers.items()} + else: + # Lowercase (and encode to utf-8 where needed) non-twisted header keys + headers = {name.lower() if isinstance(name, bytes) else name.lower().encode("utf-8"): values for name, values in headers.items()} address_header_name = address_header_name.lower().encode("utf-8") result_addr = original_addr From 13e7804187d2262a7fd1c17667fe27f7114240e7 Mon Sep 17 00:00:00 2001 From: Andrew Godwin Date: Tue, 2 Jan 2018 11:39:58 -0800 Subject: [PATCH 07/11] Releasing 1.4.0 --- CHANGELOG.txt | 9 +++++++++ daphne/__init__.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 5a1b551..f197888 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,12 @@ +1.4.0 (2018-01-02) +------------------ + +* The X-Forwarded-Proto header can now be used to pass along protocol from + a reverse proxy. + +* WebSocket headers are now correctly always passed as bytestrings. + + 1.3.0 (2017-06-16) ------------------ diff --git a/daphne/__init__.py b/daphne/__init__.py index 67bc602..3e8d9f9 100755 --- a/daphne/__init__.py +++ b/daphne/__init__.py @@ -1 +1 @@ -__version__ = "1.3.0" +__version__ = "1.4.0" From 3fcfe45e846300d36cc5b419ac6448bd7092feb8 Mon Sep 17 00:00:00 2001 From: Andrew Godwin Date: Tue, 2 Jan 2018 13:29:03 -0800 Subject: [PATCH 08/11] Add missing proto header argument to HTTPFactory --- daphne/http_protocol.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/daphne/http_protocol.py b/daphne/http_protocol.py index df9f93a..41e8552 100755 --- a/daphne/http_protocol.py +++ b/daphne/http_protocol.py @@ -312,7 +312,7 @@ class HTTPFactory(http.HTTPFactory): routed appropriately. """ - def __init__(self, channel_layer, action_logger=None, send_channel=None, timeout=120, websocket_timeout=86400, ping_interval=20, ping_timeout=30, ws_protocols=None, root_path="", websocket_connect_timeout=30, proxy_forwarded_address_header=None, proxy_forwarded_port_header=None, websocket_handshake_timeout=5): + def __init__(self, channel_layer, action_logger=None, send_channel=None, timeout=120, websocket_timeout=86400, ping_interval=20, ping_timeout=30, ws_protocols=None, root_path="", websocket_connect_timeout=30, proxy_forwarded_address_header=None, proxy_forwarded_port_header=None, proxy_forwarded_proto_header=None, websocket_handshake_timeout=5): http.HTTPFactory.__init__(self) self.channel_layer = channel_layer self.action_logger = action_logger @@ -324,6 +324,7 @@ class HTTPFactory(http.HTTPFactory): self.ping_interval = ping_interval self.proxy_forwarded_address_header = proxy_forwarded_address_header self.proxy_forwarded_port_header = proxy_forwarded_port_header + self.proxy_forwarded_proto_header = proxy_forwarded_proto_header # We track all sub-protocols for response channel mapping self.reply_protocols = {} # Make a factory for WebSocket protocols From 0c633fa9683e03fad2504d594be935fe49e1ffe5 Mon Sep 17 00:00:00 2001 From: Andrew Godwin Date: Tue, 2 Jan 2018 13:31:41 -0800 Subject: [PATCH 09/11] Releasing 1.4.1 --- CHANGELOG.txt | 7 +++++++ daphne/__init__.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index f197888..508b390 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,10 @@ +1.4.1 (2018-01-02) +------------------ + +* Bugfix for a bad merge of HTTPFactory for X-Forwarded-Proto causing Daphne + to not start. + + 1.4.0 (2018-01-02) ------------------ diff --git a/daphne/__init__.py b/daphne/__init__.py index 3e8d9f9..bf25615 100755 --- a/daphne/__init__.py +++ b/daphne/__init__.py @@ -1 +1 @@ -__version__ = "1.4.0" +__version__ = "1.4.1" From f33523237356a49b255460f77811804429d371a7 Mon Sep 17 00:00:00 2001 From: Andrew Godwin Date: Fri, 5 Jan 2018 00:39:46 -0800 Subject: [PATCH 10/11] Fix poorly captured second argument on Python 2 --- daphne/ws_protocol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daphne/ws_protocol.py b/daphne/ws_protocol.py index 08f818b..45a3ab5 100755 --- a/daphne/ws_protocol.py +++ b/daphne/ws_protocol.py @@ -57,7 +57,7 @@ class WebSocketProtocol(WebSocketServerProtocol): self.server_addr = None if self.main_factory.proxy_forwarded_address_header: - self.client_addr, = parse_x_forwarded_for( + self.client_addr, self.client_scheme = parse_x_forwarded_for( self.http_headers, self.main_factory.proxy_forwarded_address_header, self.main_factory.proxy_forwarded_port_header, From 691151b0975ac5e29059302673a14232e0d6bc8a Mon Sep 17 00:00:00 2001 From: Andrew Godwin Date: Fri, 5 Jan 2018 00:41:58 -0800 Subject: [PATCH 11/11] Releasing 1.4.2 --- CHANGELOG.txt | 6 ++++++ daphne/__init__.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 508b390..269cece 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,9 @@ +1.4.2 (2018-01-05) +------------------ + +* Bugfix for WebSocket protocol when X-Forwarded-For is turned on. + + 1.4.1 (2018-01-02) ------------------ diff --git a/daphne/__init__.py b/daphne/__init__.py index bf25615..daa50c7 100755 --- a/daphne/__init__.py +++ b/daphne/__init__.py @@ -1 +1 @@ -__version__ = "1.4.1" +__version__ = "1.4.2"