Compare commits

...

47 Commits
4.0.0 ... main

Author SHA1 Message Date
pre-commit-ci[bot]
7c9334952d
[pre-commit.ci] pre-commit autoupdate (#551)
updates:
- [github.com/psf/black: 24.10.0 → 25.1.0](https://github.com/psf/black/compare/24.10.0...25.1.0)
- [github.com/pycqa/isort: 5.13.2 → 6.0.1](https://github.com/pycqa/isort/compare/5.13.2...6.0.1)
- [github.com/PyCQA/flake8: 7.1.1 → 7.2.0](https://github.com/PyCQA/flake8/compare/7.1.1...7.2.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-04-18 06:58:38 -07:00
Andrew Sears
630caed915
Upgrade project metadata (#542) 2025-01-22 17:34:39 +01:00
pre-commit-ci[bot]
786e4c120a
[pre-commit.ci] pre-commit autoupdate (#546) 2025-01-07 07:33:08 +01:00
David Fuentes Baldomir
f0a3ec60e9
Add --nostatic and --insecure args to runserver command. (#450)
Fixes #449
2025-01-04 09:37:17 +01:00
David Smith
32ac73e1a0
Added support for Python 3.13. (#539) 2024-11-18 20:57:11 +01:00
David Smith
e25b4bcc31
Target py39-plus with pyupgrade. (#540) 2024-11-18 20:56:40 +01:00
Carlton Gibson
06afd9b94a
Drop support for EOL Python 3.8. (#536) 2024-10-28 19:03:41 -07:00
pre-commit-ci[bot]
ffad9c3cfd
[pre-commit.ci] pre-commit autoupdate (#532)
updates:
- [github.com/asottile/pyupgrade: v3.16.0 → v3.17.0](https://github.com/asottile/pyupgrade/compare/v3.16.0...v3.17.0)
- [github.com/psf/black: 24.4.2 → 24.10.0](https://github.com/psf/black/compare/24.4.2...24.10.0)
- [github.com/PyCQA/flake8: 7.1.0 → 7.1.1](https://github.com/PyCQA/flake8/compare/7.1.0...7.1.1)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-10-07 17:10:56 -07:00
Jon Janzen
862ebcd08d
Include test support files in sdist (#530)
Closes: https://github.com/django/daphne/issues/522
2024-08-26 07:02:23 -07:00
Jon Janzen
b1902e8ccd
Remove pytest-runner (#528)
Closes: https://github.com/django/daphne/issues/523
2024-08-24 11:51:43 -07:00
Robert Schütz
9ec5798c0d
fix tests with Twisted 24.7.0 (#526)
In the fixed test cases the responses now contain `HTTP/1.1` rather than
`HTTP/1.0`.
2024-08-24 20:47:58 +02:00
Jon Janzen
3607351212
Revert "Remove pytest-runner"
This reverts commit 420f065d9e.
2024-08-24 11:36:44 -07:00
Jon Janzen
420f065d9e
Remove pytest-runner
Closes: https://github.com/django/daphne/issues/523
2024-08-24 11:34:33 -07:00
pre-commit-ci[bot]
4a55faca45
[pre-commit.ci] pre-commit autoupdate (#515)
updates:
- [github.com/asottile/pyupgrade: v3.15.2 → v3.16.0](https://github.com/asottile/pyupgrade/compare/v3.15.2...v3.16.0)
- [github.com/psf/black: 24.3.0 → 24.4.2](https://github.com/psf/black/compare/24.3.0...24.4.2)
- [github.com/PyCQA/flake8: 7.0.0 → 7.1.0](https://github.com/PyCQA/flake8/compare/7.0.0...7.1.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-07-02 09:38:28 +02:00
Carlton Gibson
0f15e4595b
Fixed packaging configuration. (#510)
Use auto-discovery, but make sure daphne package is correctly listed.
2024-04-11 15:23:49 +02:00
Carlton Gibson
cf9145985b Updated version and changelog for v4.1.1 release. 2024-04-10 17:42:01 +02:00
sdc50
c0b630834c
Fix twisted.plugin install (#507) 2024-04-10 17:33:21 +02:00
pre-commit-ci[bot]
63790936d1
[pre-commit.ci] pre-commit autoupdate (#503) 2024-04-02 07:14:14 +02:00
Carlton Gibson
df0680c9ad Updated change notes and version for 4.1 release. 2024-02-10 15:39:05 +01:00
Carlton Gibson
ef24796243
Validate HTTP header names as per RFC 9110. (#500)
Fixes #497.
2024-02-10 15:31:37 +01:00
Alejandro R. Sedeño
9a282dd627
Handle Daphne-Root-Path for websockets, adding root_path to scope. (#453)
Signed-off-by: Alejandro R. Sedeño <asedeno@mit.edu>
2024-02-06 09:15:03 +01:00
Carlton Gibson
5fdc9176e5
Ignored flake8-bugbear B036. (#499)
"except BaseException: without re-raising" used in testing.py
2024-02-06 09:04:10 +01:00
pre-commit-ci[bot]
993efe62ce
[pre-commit.ci] pre-commit autoupdate (#492) 2024-01-01 19:58:51 +01:00
dependabot[bot]
c07925d53f
Bump actions/setup-python from 4 to 5 (#491) 2023-12-12 07:19:48 +01:00
Paolo Melchiorre
4d24e22c72
Fixed #489 -- Add support for Python 3.12 (#490) 2023-11-26 16:12:23 +01:00
pre-commit-ci[bot]
2d4dcbf149
[pre-commit.ci] pre-commit autoupdate (#485) 2023-10-03 12:59:12 +02:00
InvalidInterrupt
3758c514fd
Raise minimum supported Python version to 3.8 (#481) 2023-09-07 09:09:10 +02:00
dependabot[bot]
f108bbc7c1
Bump actions/checkout from 3 to 4 (#480)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 07:51:07 +02:00
pre-commit-ci[bot]
e49c39a4e5
[pre-commit.ci] pre-commit autoupdate (#477)
updates:
- [github.com/asottile/pyupgrade: v3.3.1 → v3.8.0](https://github.com/asottile/pyupgrade/compare/v3.3.1...v3.8.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2023-07-04 05:48:51 +01:00
Carlton Gibson
1eaf2206cc
Set pre-commit to quarterly updates. (#472) 2023-04-16 10:33:27 +02:00
Abenezer Belachew
09da15dc4e
Double quotes during pip (#467)
Single quotes return => ERROR: Invalid requirement: "'Twisted[tls,http2]'"
2023-04-14 15:10:16 +02:00
pre-commit-ci[bot]
21513b84da
[pre-commit.ci] pre-commit autoupdate (#470)
updates:
- [github.com/psf/black: 23.1.0 → 23.3.0](https://github.com/psf/black/compare/23.1.0...23.3.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Carlton Gibson <carlton.gibson@noumenal.es>
2023-04-14 15:03:51 +02:00
Carlton Gibson
077dd81809
Added missing stacklevel warning parameter. (#471) 2023-04-14 14:53:12 +02:00
pre-commit-ci[bot]
b0204165b1
[pre-commit.ci] pre-commit autoupdate (#466)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2023-02-07 15:20:08 +00:00
pre-commit-ci[bot]
79fd65dec3
[pre-commit.ci] pre-commit autoupdate (#464)
updates:
- [github.com/pycqa/isort: 5.11.4 → 5.12.0](https://github.com/pycqa/isort/compare/5.11.4...5.12.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2023-01-31 06:52:32 +00:00
pre-commit-ci[bot]
5681d71c17
[pre-commit.ci] pre-commit autoupdate (#462)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-12-29 12:19:00 +00:00
pre-commit-ci[bot]
fdc944a280
[pre-commit.ci] pre-commit autoupdate (#461)
updates:
- [github.com/pycqa/isort: 5.11.0 → v5.11.3](https://github.com/pycqa/isort/compare/5.11.0...v5.11.3)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-12-20 10:37:51 +01:00
pre-commit-ci[bot]
c9343aa9d6
[pre-commit.ci] pre-commit autoupdate (#460)
updates:
- [github.com/asottile/pyupgrade: v3.3.0 → v3.3.1](https://github.com/asottile/pyupgrade/compare/v3.3.0...v3.3.1)
- [github.com/psf/black: 22.10.0 → 22.12.0](https://github.com/psf/black/compare/22.10.0...22.12.0)
- [github.com/pycqa/isort: 5.10.1 → 5.11.0](https://github.com/pycqa/isort/compare/5.10.1...5.11.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-12-12 23:15:35 +00:00
Adam Johnson
d59c2bd424
Upgrade to tox 4 (#458) 2022-12-08 01:06:41 +00:00
pre-commit-ci[bot]
2015ecdd8f
[pre-commit.ci] pre-commit autoupdate (#457)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-12-06 09:01:28 +00:00
pre-commit-ci[bot]
18e936eed1
[pre-commit.ci] pre-commit autoupdate (#456)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-11-29 20:34:37 +00:00
Michael K
ef946d5637
Upgrade GitHub Actions actions (#454)
And set up dependabot to take care of them in the future.
2022-11-18 11:33:03 +01:00
pre-commit-ci[bot]
a0b2ac0e8f
[pre-commit.ci] pre-commit autoupdate (#452)
updates:
- [github.com/asottile/pyupgrade: v3.2.0 → v3.2.2](https://github.com/asottile/pyupgrade/compare/v3.2.0...v3.2.2)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-11-14 20:47:53 +00:00
pre-commit-ci[bot]
afd0d51b83
[pre-commit.ci] pre-commit autoupdate (#448)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-11-01 11:09:39 +00:00
Michael K
d5fbdfc4cb
Run tests against Python 3.11 and add trove classifier (#446) 2022-10-25 13:46:20 +01:00
pre-commit-ci[bot]
71be46265d
[pre-commit.ci] pre-commit autoupdate (#444)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-10-17 23:09:03 +01:00
pre-commit-ci[bot]
91c61f4ff4
[pre-commit.ci] pre-commit autoupdate (#443)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-10-10 23:39:20 +01:00
22 changed files with 252 additions and 100 deletions

11
.flake8 Normal file
View File

@ -0,0 +1,11 @@
[flake8]
exclude =
.venv,
.tox,
docs,
testproject,
js_client,
.eggs
extend-ignore = E123, E128, E266, E402, W503, E731, W601, B036
max-line-length = 120

6
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly

View File

@ -5,6 +5,10 @@ on:
branches:
- main
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
tests:
@ -16,23 +20,24 @@ jobs:
- ubuntu
- windows
python-version:
- "3.7"
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
python -m pip install --upgrade tox tox-py
python -m pip install --upgrade tox
- name: Run tox targets for ${{ matrix.python-version }}
run: tox --py current
run: tox run -f py$(echo ${{ matrix.python-version }} | tr -d .)

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ test_consumer*
.python-version
.pytest_cache/
.vscode
.coverage

View File

@ -1,21 +1,23 @@
repos:
- repo: https://github.com/asottile/pyupgrade
rev: v2.38.2
rev: v3.19.1
hooks:
- id: pyupgrade
args: [--py36-plus]
args: [--py39-plus]
- repo: https://github.com/psf/black
rev: 22.8.0
rev: 25.1.0
hooks:
- id: black
language_version: python3
- repo: https://github.com/pycqa/isort
rev: 5.10.1
rev: 6.0.1
hooks:
- id: isort
- repo: https://github.com/PyCQA/flake8
rev: 5.0.4
rev: 7.2.0
hooks:
- id: flake8
additional_dependencies:
- flake8-bugbear
ci:
autoupdate_schedule: quarterly

View File

@ -1,3 +1,37 @@
4.2.0 (to be released)
------------------
* Added support for Python 3.13.
* Drop support for EOL Python 3.8.
* Removed unused pytest-runner
* Fixed sdist file to ensure it includes all tests
4.1.2 (2024-04-11)
------------------
* Fixed a setuptools configuration error in 4.1.1.
4.1.1 (2024-04-10)
------------------
* Fixed a twisted.plugin packaging error in 4.1.0.
Thanks to sdc50.
4.1.0 (2024-02-10)
------------------
* Added support for Python 3.12.
* Dropped support for EOL Python 3.7.
* Handled root path for websocket scopes.
* Validate HTTP header names as per RFC 9110.
4.0.0 (2022-10-07)
------------------

View File

@ -1 +1,2 @@
include LICENSE
recursive-include tests *.py

View File

@ -54,7 +54,7 @@ Daphne 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::
@ -108,7 +108,7 @@ should start with a slash, but not end with one; for example::
Python Support
--------------
Daphne requires Python 3.7 or later.
Daphne requires Python 3.9 or later.
Contributing

View File

@ -1,6 +1,6 @@
import sys
__version__ = "4.0.0"
__version__ = "4.1.3"
# Windows on Python 3.8+ uses ProactorEventLoop, which is not compatible with

View File

@ -270,16 +270,16 @@ class CommandLineInterface:
websocket_connect_timeout=args.websocket_connect_timeout,
websocket_handshake_timeout=args.websocket_connect_timeout,
application_close_timeout=args.application_close_timeout,
action_logger=AccessLogGenerator(access_log_stream)
if access_log_stream
else None,
action_logger=(
AccessLogGenerator(access_log_stream) if access_log_stream else None
),
root_path=args.root_path,
verbosity=args.verbosity,
proxy_forwarded_address_header=self._get_forwarded_host(args=args),
proxy_forwarded_port_header=self._get_forwarded_port(args=args),
proxy_forwarded_proto_header="X-Forwarded-Proto"
if args.proxy_headers
else None,
proxy_forwarded_proto_header=(
"X-Forwarded-Proto" if args.proxy_headers else None
),
server_name=args.server_name,
)
self.server.run()

View File

@ -9,7 +9,7 @@ from twisted.protocols.policies import ProtocolWrapper
from twisted.web import http
from zope.interface import implementer
from .utils import parse_x_forwarded_for
from .utils import HEADER_NAME_RE, parse_x_forwarded_for
logger = logging.getLogger(__name__)
@ -69,6 +69,13 @@ class WebRequest(http.Request):
def process(self):
try:
self.request_start = time.time()
# Validate header names.
for name, _ in self.requestHeaders.getAllRawHeaders():
if not HEADER_NAME_RE.fullmatch(name):
self.basic_error(400, b"Bad Request", "Invalid header name")
return
# Get upgrade header
upgrade_header = None
if self.requestHeaders.hasHeader(b"Upgrade"):
@ -279,9 +286,11 @@ class WebRequest(http.Request):
"path": uri,
"status": self.code,
"method": self.method.decode("ascii", "replace"),
"client": "%s:%s" % tuple(self.client_addr)
"client": (
"%s:%s" % tuple(self.client_addr)
if self.client_addr
else None,
else None
),
"time_taken": self.duration(),
"size": self.sentLength,
},

View File

@ -73,6 +73,18 @@ class Command(RunserverCommand):
"seconds (default: 5)"
),
)
parser.add_argument(
"--nostatic",
action="store_false",
dest="use_static_handler",
help="Tells Django to NOT automatically serve static files at STATIC_URL.",
)
parser.add_argument(
"--insecure",
action="store_true",
dest="insecure_serving",
help="Allows serving static files even if DEBUG is False.",
)
def handle(self, *args, **options):
self.http_timeout = options.get("http_timeout", None)

View File

@ -21,6 +21,7 @@ if current_reactor is not None:
+ "you can fix this warning by importing daphne.server early in your codebase or "
+ "finding the package that imports Twisted and importing it later on.",
UserWarning,
stacklevel=2,
)
del sys.modules["twisted.internet.reactor"]
asyncioreactor.install(twisted_loop)

View File

@ -158,7 +158,7 @@ class DaphneProcess(multiprocessing.Process):
application=application,
endpoints=endpoints,
signal_handlers=False,
**self.kwargs
**self.kwargs,
)
# Set up a poller to look for the port
reactor.callLater(0.1, self.resolve_port)

View File

@ -1,7 +1,12 @@
import importlib
import re
from twisted.web.http_headers import Headers
# Header name regex as per h11.
# https://github.com/python-hyper/h11/blob/a2c68948accadc3876dffcf979d98002e4a4ed27/h11/_abnf.py#L10-L21
HEADER_NAME_RE = re.compile(rb"[-!#$%&'*+.^_`|~0-9a-zA-Z]+")
def import_by_path(path):
"""

View File

@ -31,16 +31,20 @@ class WebSocketProtocol(WebSocketServerProtocol):
self.server.protocol_connected(self)
self.request = request
self.protocol_to_accept = None
self.root_path = self.server.root_path
self.socket_opened = time.time()
self.last_ping = time.time()
try:
# Sanitize and decode headers
# Sanitize and decode headers, potentially extracting root path
self.clean_headers = []
for name, value in request.headers.items():
name = name.encode("ascii")
# Prevent CVE-2015-0219
if b"_" in name:
continue
if name.lower() == b"daphne-root-path":
self.root_path = unquote(value)
else:
self.clean_headers.append((name.lower(), value.encode("latin1")))
# Get client address if possible
peer = self.transport.getPeer()
@ -76,6 +80,7 @@ class WebSocketProtocol(WebSocketServerProtocol):
"type": "websocket",
"path": unquote(self.path.decode("ascii")),
"raw_path": self.path,
"root_path": self.root_path,
"headers": self.clean_headers,
"query_string": self._raw_query_string, # Passed by HTTP protocol
"client": self.client_addr,
@ -110,9 +115,9 @@ class WebSocketProtocol(WebSocketServerProtocol):
"connecting",
{
"path": self.request.path,
"client": "%s:%s" % tuple(self.client_addr)
if self.client_addr
else None,
"client": (
"%s:%s" % tuple(self.client_addr) if self.client_addr else None
),
},
)
@ -133,9 +138,9 @@ class WebSocketProtocol(WebSocketServerProtocol):
"connected",
{
"path": self.request.path,
"client": "%s:%s" % tuple(self.client_addr)
if self.client_addr
else None,
"client": (
"%s:%s" % tuple(self.client_addr) if self.client_addr else None
),
},
)
@ -170,9 +175,9 @@ class WebSocketProtocol(WebSocketServerProtocol):
"disconnected",
{
"path": self.request.path,
"client": "%s:%s" % tuple(self.client_addr)
if self.client_addr
else None,
"client": (
"%s:%s" % tuple(self.client_addr) if self.client_addr else None
),
},
)
@ -237,9 +242,9 @@ class WebSocketProtocol(WebSocketServerProtocol):
"rejected",
{
"path": self.request.path,
"client": "%s:%s" % tuple(self.client_addr)
if self.client_addr
else None,
"client": (
"%s:%s" % tuple(self.client_addr) if self.client_addr else None
),
},
)

81
pyproject.toml Normal file
View File

@ -0,0 +1,81 @@
[project]
name = "daphne"
dynamic = ["version"]
description = "Django ASGI (HTTP/WebSocket) server"
requires-python = ">=3.9"
authors = [
{ name = "Django Software Foundation", email = "foundation@djangoproject.com" },
]
license = { text = "BSD" }
classifiers = [
"Development Status :: 4 - Beta",
"Environment :: Web Environment",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Internet :: WWW/HTTP",
]
dependencies = ["asgiref>=3.5.2,<4", "autobahn>=22.4.2", "twisted[tls]>=22.4"]
[project.optional-dependencies]
tests = [
"django",
"hypothesis",
"pytest",
"pytest-asyncio",
"pytest-cov",
"black",
"tox",
"flake8",
"flake8-bugbear",
"mypy",
]
[project.urls]
homepage = "https://github.com/django/daphne"
documentation = "https://channels.readthedocs.io"
repository = "https://github.com/django/daphne.git"
changelog = "https://github.com/django/daphne/blob/main/CHANGELOG.txt"
issues = "https://github.com/django/daphne/issues"
[project.scripts]
daphne = "daphne.cli:CommandLineInterface.entrypoint"
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[tool.setuptools]
packages = ["daphne"]
[tool.setuptools.dynamic]
version = { attr = "daphne.__version__" }
readme = { file = "README.rst", content-type = "text/x-rst" }
[tool.isort]
profile = "black"
[tool.pytest]
testpaths = ["tests"]
asyncio_mode = "strict"
filterwarnings = ["ignore::pytest.PytestDeprecationWarning"]
[tool.coverage.run]
omit = ["tests/*"]
concurrency = ["multiprocessing"]
[tool.coverage.report]
show_missing = "true"
skip_covered = "true"
[tool.coverage.html]
directory = "reports/coverage_html_report"

View File

@ -1,11 +0,0 @@
[flake8]
exclude = venv/*,tox/*,docs/*,testproject/*,js_client/*,.eggs/*
extend-ignore = E123, E128, E266, E402, W503, E731, W601
max-line-length = 120
[isort]
profile = black
[tool:pytest]
testpaths = tests
asyncio_mode = strict

View File

@ -1,46 +0,0 @@
import os
from setuptools import find_packages, setup
from daphne import __version__
# We use the README as the long_description
readme_path = os.path.join(os.path.dirname(__file__), "README.rst")
with open(readme_path) as fp:
long_description = fp.read()
setup(
name="daphne",
version=__version__,
url="https://github.com/django/daphne",
author="Django Software Foundation",
author_email="foundation@djangoproject.com",
description="Django ASGI (HTTP/WebSocket) server",
long_description=long_description,
license="BSD",
zip_safe=False,
package_dir={"twisted": "daphne/twisted"},
packages=find_packages() + ["twisted.plugins"],
include_package_data=True,
install_requires=["twisted[tls]>=22.4", "autobahn>=22.4.2", "asgiref>=3.5.2,<4"],
python_requires=">=3.7",
setup_requires=["pytest-runner"],
extras_require={"tests": ["hypothesis", "pytest", "pytest-asyncio", "django"]},
entry_points={
"console_scripts": ["daphne = daphne.cli:CommandLineInterface.entrypoint"]
},
classifiers=[
"Development Status :: 4 - Beta",
"Environment :: Web Environment",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Topic :: Internet :: WWW/HTTP",
],
)

View File

@ -304,9 +304,21 @@ class TestHTTPRequest(DaphneTestCase):
response = self.run_daphne_raw(
b"GET /\xc3\xa4\xc3\xb6\xc3\xbc HTTP/1.0\r\n\r\n"
)
self.assertTrue(response.startswith(b"HTTP/1.0 400 Bad Request"))
self.assertTrue(b"400 Bad Request" in response)
# Bad querystring
response = self.run_daphne_raw(
b"GET /?\xc3\xa4\xc3\xb6\xc3\xbc HTTP/1.0\r\n\r\n"
)
self.assertTrue(response.startswith(b"HTTP/1.0 400 Bad Request"))
self.assertTrue(b"400 Bad Request" in response)
def test_invalid_header_name(self):
"""
Tests that requests with invalid header names fail.
"""
# Test cases follow those used by h11
# https://github.com/python-hyper/h11/blob/a2c68948accadc3876dffcf979d98002e4a4ed27/h11/tests/test_headers.py#L24-L35
for header_name in [b"foo bar", b"foo\x00bar", b"foo\xffbar", b"foo\x01bar"]:
response = self.run_daphne_raw(
f"GET / HTTP/1.0\r\n{header_name}: baz\r\n\r\n".encode("ascii")
)
self.assertTrue(b"400 Bad Request" in response)

View File

@ -192,6 +192,30 @@ class TestWebsocket(DaphneTestCase):
self.assertEqual(scope["path"], "/foo/bar")
self.assertEqual(scope["raw_path"], b"/foo%2Fbar")
@given(daphne_path=http_strategies.http_path())
@settings(max_examples=5, deadline=2000)
def test_root_path(self, *, daphne_path):
"""
Tests root_path handling.
"""
headers = [("Daphne-Root-Path", parse.quote(daphne_path))]
with DaphneTestingInstance() as test_app:
test_app.add_send_messages([{"type": "websocket.accept"}])
self.websocket_handshake(
test_app,
path="/",
headers=headers,
)
# Validate the scope and messages we got
scope, _ = test_app.get_received()
# Daphne-Root-Path is not included in the returned 'headers' section.
self.assertNotIn(
"daphne-root-path", (header[0].lower() for header in scope["headers"])
)
# And what we're looking for, root_path being set.
self.assertEqual(scope["root_path"], daphne_path)
def test_text_frames(self):
"""
Tests we can send and receive text frames.

View File

@ -1,8 +1,8 @@
[tox]
envlist =
py{37,38,39,310}
py{39,310,311,312,313}
[testenv]
usedevelop = true
extras = tests
commands =
pytest -v {posargs}