Fixed #24: Configurable root_name options

This commit is contained in:
Andrew Godwin 2016-06-21 08:15:10 -07:00
parent 66e005f277
commit 5a451ab06a
4 changed files with 38 additions and 3 deletions

View File

@ -14,6 +14,7 @@ to power Django Channels.
It supports automatic negotiation of protocols; there's no need for URL
prefixing to determine WebSocket endpoints versus HTTP endpoints.
Running
-------
@ -21,3 +22,21 @@ Simply point Daphne to your ASGI channel layer instance, and optionally
set a bind address and port (defaults to localhost, port 8000)::
daphne -b 0.0.0.0 -p 8001 django_project.asgi:channel_layer
Root Path (SCRIPT_NAME)
-----------------------
In order to set the root path for Daphne, which is the equivalent of the
WSGI ``SCRIPT_NAME`` setting, you have two options:
* Pass a header value ``DAPHNE_ROOT_PATH``, with the desired root path as a
URLencoded ASCII value
* Set the ``--root-path`` commandline option with the desired root path as a
URLencoded ASCII value
The header takes precedence if both are set. As with ``SCRIPT_ALIAS``, the value
should start with a slash, but not end with one; for example::
daphne --root-path=/forum django_project.asgi:channel_layer

View File

@ -77,6 +77,12 @@ class CommandLineInterface(object):
help='The WebSocket protocols you wish to support',
default=None,
)
self.parser.add_argument(
'--root-path',
dest='root_path',
help='The setting for the ASGI root_path variable',
default="",
)
@classmethod
def entrypoint(cls):
@ -131,4 +137,5 @@ class CommandLineInterface(object):
ping_interval=args.ping_interval,
action_logger=AccessLogGenerator(access_log_stream) if access_log_stream else None,
ws_protocols=args.ws_protocols,
root_path=args.root_path,
).run()

View File

@ -109,13 +109,17 @@ class WebRequest(http.Request):
self.reply_channel = None
# Boring old HTTP.
else:
# Sanitize and decode headers
# Sanitize and decode headers, potentially extracting root path
self.clean_headers = []
self.root_path = self.factory.root_path
for name, values in self.requestHeaders.getAllRawHeaders():
# Prevent CVE-2015-0219
if b"_" in name:
continue
for value in values:
if name.lower() == "asgi_root_path":
self.root_path = self.unquote(value)
else:
self.clean_headers.append((name.lower(), value))
logger.debug("HTTP %s request for %s", self.method, self.reply_channel)
self.content.seek(0, 0)
@ -127,6 +131,7 @@ class WebRequest(http.Request):
"http_version": "1.1",
"method": self.method.decode("ascii"),
"path": self.unquote(self.path),
"root_path": self.root_path,
"scheme": "http",
"query_string": self.unquote(self.query_string, plus_as_space=True),
"headers": self.clean_headers,
@ -268,7 +273,7 @@ class HTTPFactory(http.HTTPFactory):
protocol = HTTPProtocol
def __init__(self, channel_layer, action_logger=None, timeout=120, websocket_timeout=86400, ping_interval=20, ws_protocols=None):
def __init__(self, channel_layer, action_logger=None, timeout=120, websocket_timeout=86400, ping_interval=20, ws_protocols=None, root_path=""):
http.HTTPFactory.__init__(self)
self.channel_layer = channel_layer
self.action_logger = action_logger
@ -281,6 +286,7 @@ class HTTPFactory(http.HTTPFactory):
self.ws_factory = WebSocketFactory(self, protocols=ws_protocols)
self.ws_factory.protocol = WebSocketProtocol
self.ws_factory.reply_protocols = self.reply_protocols
self.root_path = root_path
def reply_channels(self):
return self.reply_protocols.keys()

View File

@ -20,6 +20,7 @@ class Server(object):
websocket_timeout=None,
ping_interval=20,
ws_protocols=None,
root_path="",
):
self.channel_layer = channel_layer
self.host = host
@ -33,6 +34,7 @@ class Server(object):
# 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)
self.ws_protocols = ws_protocols
self.root_path = root_path
def run(self):
self.factory = HTTPFactory(
@ -42,6 +44,7 @@ class Server(object):
websocket_timeout=self.websocket_timeout,
ping_interval=self.ping_interval,
ws_protocols=self.ws_protocols,
root_path=self.root_path,
)
if self.unix_socket:
reactor.listenUNIX(self.unix_socket, self.factory)