mirror of
https://github.com/django/daphne.git
synced 2026-03-12 23:02:44 +03:00
Compare commits
No commits in common. "main" and "4.1.0" have entirely different histories.
11
.flake8
11
.flake8
|
|
@ -1,11 +0,0 @@
|
||||||
[flake8]
|
|
||||||
exclude =
|
|
||||||
.venv,
|
|
||||||
.tox,
|
|
||||||
docs,
|
|
||||||
testproject,
|
|
||||||
js_client,
|
|
||||||
.eggs
|
|
||||||
|
|
||||||
extend-ignore = E123, E128, E266, E402, W503, E731, W601, B036
|
|
||||||
max-line-length = 120
|
|
||||||
10
.github/workflows/tests.yml
vendored
10
.github/workflows/tests.yml
vendored
|
|
@ -5,10 +5,6 @@ on:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
pull_request:
|
pull_request:
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tests:
|
tests:
|
||||||
|
|
@ -20,17 +16,17 @@ jobs:
|
||||||
- ubuntu
|
- ubuntu
|
||||||
- windows
|
- windows
|
||||||
python-version:
|
python-version:
|
||||||
|
- "3.8"
|
||||||
- "3.9"
|
- "3.9"
|
||||||
- "3.10"
|
- "3.10"
|
||||||
- "3.11"
|
- "3.11"
|
||||||
- "3.12"
|
- "3.12"
|
||||||
- "3.13"
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -13,4 +13,3 @@ test_consumer*
|
||||||
.python-version
|
.python-version
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
.vscode
|
.vscode
|
||||||
.coverage
|
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
rev: v3.20.0
|
rev: v3.15.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
args: [--py39-plus]
|
args: [--py38-plus]
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 25.1.0
|
rev: 23.12.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
language_version: python3
|
language_version: python3
|
||||||
- repo: https://github.com/pycqa/isort
|
- repo: https://github.com/pycqa/isort
|
||||||
rev: 6.0.1
|
rev: 5.13.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: isort
|
- id: isort
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 7.3.0
|
rev: 6.1.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1,3 @@
|
||||||
4.2.1 (2025-07-02)
|
|
||||||
------------------
|
|
||||||
|
|
||||||
* Fixed a packaging error in 4.2.0.
|
|
||||||
|
|
||||||
* Removed --nostatic and --insecure args to runserver command when staticfiles
|
|
||||||
app is not installed.
|
|
||||||
|
|
||||||
4.2.0 (2025-05-16)
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Daphne 4.2 is a maintenance release in the 4.x series.
|
|
||||||
|
|
||||||
* Added support for Python 3.13.
|
|
||||||
|
|
||||||
* Dropped support for EOL Python 3.8.
|
|
||||||
|
|
||||||
* Updated pyupgrade configuration to target Python 3.9.
|
|
||||||
|
|
||||||
* Added a `load_asgi_app` hook to CLI class, useful for compiled or frozen
|
|
||||||
applications.
|
|
||||||
|
|
||||||
* Allowed assigning a port in the DaphneProcess test helper, useful for live
|
|
||||||
server test cases, such as that provided by Channels.
|
|
||||||
|
|
||||||
* Added --nostatic and --insecure args to runserver command to match Django's
|
|
||||||
built-in command.
|
|
||||||
|
|
||||||
* Moved metadata to use pyproject.toml.
|
|
||||||
|
|
||||||
* Updated sdist file to include tests and changelog.
|
|
||||||
|
|
||||||
* Removed unused pytest-runner.
|
|
||||||
|
|
||||||
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)
|
4.1.0 (2024-02-10)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1 @@
|
||||||
include LICENSE
|
include LICENSE
|
||||||
include CHANGELOG.txt
|
|
||||||
recursive-include tests *.py
|
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ should start with a slash, but not end with one; for example::
|
||||||
Python Support
|
Python Support
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Daphne requires Python 3.9 or later.
|
Daphne requires Python 3.8 or later.
|
||||||
|
|
||||||
|
|
||||||
Contributing
|
Contributing
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
__version__ = "4.2.1"
|
__version__ = "4.1.0"
|
||||||
|
|
||||||
|
|
||||||
# Windows on Python 3.8+ uses ProactorEventLoop, which is not compatible with
|
# Windows on Python 3.8+ uses ProactorEventLoop, which is not compatible with
|
||||||
|
|
|
||||||
|
|
@ -201,12 +201,6 @@ class CommandLineInterface:
|
||||||
if args.proxy_headers:
|
if args.proxy_headers:
|
||||||
return "X-Forwarded-Port"
|
return "X-Forwarded-Port"
|
||||||
|
|
||||||
def load_asgi_app(self, asgi_app_path: str):
|
|
||||||
"""
|
|
||||||
Return the imported application.
|
|
||||||
"""
|
|
||||||
return import_by_path(asgi_app_path)
|
|
||||||
|
|
||||||
def run(self, args):
|
def run(self, args):
|
||||||
"""
|
"""
|
||||||
Pass in raw argument list and it will decode them
|
Pass in raw argument list and it will decode them
|
||||||
|
|
@ -236,7 +230,7 @@ class CommandLineInterface:
|
||||||
|
|
||||||
# Import application
|
# Import application
|
||||||
sys.path.insert(0, ".")
|
sys.path.insert(0, ".")
|
||||||
application = self.load_asgi_app(args.application)
|
application = import_by_path(args.application)
|
||||||
application = guarantee_single_callable(application)
|
application = guarantee_single_callable(application)
|
||||||
|
|
||||||
# Set up port/host bindings
|
# Set up port/host bindings
|
||||||
|
|
@ -276,18 +270,16 @@ class CommandLineInterface:
|
||||||
websocket_connect_timeout=args.websocket_connect_timeout,
|
websocket_connect_timeout=args.websocket_connect_timeout,
|
||||||
websocket_handshake_timeout=args.websocket_connect_timeout,
|
websocket_handshake_timeout=args.websocket_connect_timeout,
|
||||||
application_close_timeout=args.application_close_timeout,
|
application_close_timeout=args.application_close_timeout,
|
||||||
action_logger=(
|
action_logger=AccessLogGenerator(access_log_stream)
|
||||||
AccessLogGenerator(access_log_stream) if access_log_stream else None
|
if access_log_stream
|
||||||
),
|
else None,
|
||||||
root_path=args.root_path,
|
root_path=args.root_path,
|
||||||
verbosity=args.verbosity,
|
verbosity=args.verbosity,
|
||||||
proxy_forwarded_address_header=self._get_forwarded_host(args=args),
|
proxy_forwarded_address_header=self._get_forwarded_host(args=args),
|
||||||
proxy_forwarded_port_header=self._get_forwarded_port(args=args),
|
proxy_forwarded_port_header=self._get_forwarded_port(args=args),
|
||||||
proxy_forwarded_proto_header=(
|
proxy_forwarded_proto_header="X-Forwarded-Proto"
|
||||||
"X-Forwarded-Proto" if args.proxy_headers else None
|
if args.proxy_headers
|
||||||
),
|
else None,
|
||||||
server_name=args.server_name,
|
server_name=args.server_name,
|
||||||
)
|
)
|
||||||
self.server.run()
|
self.server.run()
|
||||||
if self.server.abort_start:
|
|
||||||
exit(1)
|
|
||||||
|
|
|
||||||
|
|
@ -286,11 +286,9 @@ class WebRequest(http.Request):
|
||||||
"path": uri,
|
"path": uri,
|
||||||
"status": self.code,
|
"status": self.code,
|
||||||
"method": self.method.decode("ascii", "replace"),
|
"method": self.method.decode("ascii", "replace"),
|
||||||
"client": (
|
"client": "%s:%s" % tuple(self.client_addr)
|
||||||
"%s:%s" % tuple(self.client_addr)
|
if self.client_addr
|
||||||
if self.client_addr
|
else None,
|
||||||
else None
|
|
||||||
),
|
|
||||||
"time_taken": self.duration(),
|
"time_taken": self.duration(),
|
||||||
"size": self.sentLength,
|
"size": self.sentLength,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -73,19 +73,6 @@ class Command(RunserverCommand):
|
||||||
"seconds (default: 5)"
|
"seconds (default: 5)"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
if apps.is_installed("django.contrib.staticfiles"):
|
|
||||||
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):
|
def handle(self, *args, **options):
|
||||||
self.http_timeout = options.get("http_timeout", None)
|
self.http_timeout = options.get("http_timeout", None)
|
||||||
|
|
|
||||||
|
|
@ -126,16 +126,14 @@ class DaphneProcess(multiprocessing.Process):
|
||||||
port it ends up listening on back to the parent process.
|
port it ends up listening on back to the parent process.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, host, get_application, kwargs=None, setup=None, teardown=None):
|
||||||
self, host, get_application, kwargs=None, setup=None, teardown=None, port=None
|
|
||||||
):
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.host = host
|
self.host = host
|
||||||
self.get_application = get_application
|
self.get_application = get_application
|
||||||
self.kwargs = kwargs or {}
|
self.kwargs = kwargs or {}
|
||||||
self.setup = setup
|
self.setup = setup
|
||||||
self.teardown = teardown
|
self.teardown = teardown
|
||||||
self.port = multiprocessing.Value("i", port if port is not None else 0)
|
self.port = multiprocessing.Value("i")
|
||||||
self.ready = multiprocessing.Event()
|
self.ready = multiprocessing.Event()
|
||||||
self.errors = multiprocessing.Queue()
|
self.errors = multiprocessing.Queue()
|
||||||
|
|
||||||
|
|
@ -155,14 +153,12 @@ class DaphneProcess(multiprocessing.Process):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Create the server class
|
# Create the server class
|
||||||
endpoints = build_endpoint_description_strings(
|
endpoints = build_endpoint_description_strings(host=self.host, port=0)
|
||||||
host=self.host, port=self.port.value
|
|
||||||
)
|
|
||||||
self.server = Server(
|
self.server = Server(
|
||||||
application=application,
|
application=application,
|
||||||
endpoints=endpoints,
|
endpoints=endpoints,
|
||||||
signal_handlers=False,
|
signal_handlers=False,
|
||||||
**self.kwargs,
|
**self.kwargs
|
||||||
)
|
)
|
||||||
# Set up a poller to look for the port
|
# Set up a poller to look for the port
|
||||||
reactor.callLater(0.1, self.resolve_port)
|
reactor.callLater(0.1, self.resolve_port)
|
||||||
|
|
|
||||||
|
|
@ -115,9 +115,9 @@ class WebSocketProtocol(WebSocketServerProtocol):
|
||||||
"connecting",
|
"connecting",
|
||||||
{
|
{
|
||||||
"path": self.request.path,
|
"path": self.request.path,
|
||||||
"client": (
|
"client": "%s:%s" % tuple(self.client_addr)
|
||||||
"%s:%s" % tuple(self.client_addr) if self.client_addr else None
|
if self.client_addr
|
||||||
),
|
else None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -138,9 +138,9 @@ class WebSocketProtocol(WebSocketServerProtocol):
|
||||||
"connected",
|
"connected",
|
||||||
{
|
{
|
||||||
"path": self.request.path,
|
"path": self.request.path,
|
||||||
"client": (
|
"client": "%s:%s" % tuple(self.client_addr)
|
||||||
"%s:%s" % tuple(self.client_addr) if self.client_addr else None
|
if self.client_addr
|
||||||
),
|
else None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -175,9 +175,9 @@ class WebSocketProtocol(WebSocketServerProtocol):
|
||||||
"disconnected",
|
"disconnected",
|
||||||
{
|
{
|
||||||
"path": self.request.path,
|
"path": self.request.path,
|
||||||
"client": (
|
"client": "%s:%s" % tuple(self.client_addr)
|
||||||
"%s:%s" % tuple(self.client_addr) if self.client_addr else None
|
if self.client_addr
|
||||||
),
|
else None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -242,9 +242,9 @@ class WebSocketProtocol(WebSocketServerProtocol):
|
||||||
"rejected",
|
"rejected",
|
||||||
{
|
{
|
||||||
"path": self.request.path,
|
"path": self.request.path,
|
||||||
"client": (
|
"client": "%s:%s" % tuple(self.client_addr)
|
||||||
"%s:%s" % tuple(self.client_addr) if self.client_addr else None
|
if self.client_addr
|
||||||
),
|
else None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,81 +1,3 @@
|
||||||
[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]
|
[build-system]
|
||||||
requires = ["setuptools"]
|
requires = ["setuptools"]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
[tool.setuptools]
|
|
||||||
package-dir = { daphne = "daphne", twisted = "daphne/twisted" }
|
|
||||||
|
|
||||||
[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"
|
|
||||||
|
|
|
||||||
61
setup.cfg
Normal file
61
setup.cfg
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
[metadata]
|
||||||
|
name = daphne
|
||||||
|
version = attr: daphne.__version__
|
||||||
|
url = https://github.com/django/daphne
|
||||||
|
author = Django Software Foundation
|
||||||
|
author_email = foundation@djangoproject.com
|
||||||
|
description = Django ASGI (HTTP/WebSocket) server
|
||||||
|
long_description = file: README.rst
|
||||||
|
long_description_content_type = text/x-rst
|
||||||
|
license = 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.8
|
||||||
|
Programming Language :: Python :: 3.9
|
||||||
|
Programming Language :: Python :: 3.10
|
||||||
|
Programming Language :: Python :: 3.11
|
||||||
|
Programming Language :: Python :: 3.12
|
||||||
|
Topic :: Internet :: WWW/HTTP
|
||||||
|
|
||||||
|
[options]
|
||||||
|
package_dir =
|
||||||
|
twisted=daphne/twisted
|
||||||
|
packages = find:
|
||||||
|
include_package_data = True
|
||||||
|
install_requires =
|
||||||
|
asgiref>=3.5.2,<4
|
||||||
|
autobahn>=22.4.2
|
||||||
|
twisted[tls]>=22.4
|
||||||
|
python_requires = >=3.8
|
||||||
|
setup_requires =
|
||||||
|
pytest-runner
|
||||||
|
zip_safe = False
|
||||||
|
|
||||||
|
[options.entry_points]
|
||||||
|
console_scripts =
|
||||||
|
daphne = daphne.cli:CommandLineInterface.entrypoint
|
||||||
|
|
||||||
|
[options.extras_require]
|
||||||
|
tests =
|
||||||
|
django
|
||||||
|
hypothesis
|
||||||
|
pytest
|
||||||
|
pytest-asyncio
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
exclude = venv/*,tox/*,docs/*,testproject/*,js_client/*,.eggs/*
|
||||||
|
extend-ignore = E123, E128, E266, E402, W503, E731, W601, B036
|
||||||
|
max-line-length = 120
|
||||||
|
|
||||||
|
[isort]
|
||||||
|
profile = black
|
||||||
|
|
||||||
|
[tool:pytest]
|
||||||
|
testpaths = tests
|
||||||
|
asyncio_mode = strict
|
||||||
|
|
@ -81,8 +81,6 @@ class TestCLIInterface(TestCase):
|
||||||
Mock server object for testing.
|
Mock server object for testing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
abort_start = False
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.init_kwargs = kwargs
|
self.init_kwargs = kwargs
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -304,12 +304,12 @@ class TestHTTPRequest(DaphneTestCase):
|
||||||
response = self.run_daphne_raw(
|
response = self.run_daphne_raw(
|
||||||
b"GET /\xc3\xa4\xc3\xb6\xc3\xbc HTTP/1.0\r\n\r\n"
|
b"GET /\xc3\xa4\xc3\xb6\xc3\xbc HTTP/1.0\r\n\r\n"
|
||||||
)
|
)
|
||||||
self.assertTrue(b"400 Bad Request" in response)
|
self.assertTrue(response.startswith(b"HTTP/1.0 400 Bad Request"))
|
||||||
# Bad querystring
|
# Bad querystring
|
||||||
response = self.run_daphne_raw(
|
response = self.run_daphne_raw(
|
||||||
b"GET /?\xc3\xa4\xc3\xb6\xc3\xbc HTTP/1.0\r\n\r\n"
|
b"GET /?\xc3\xa4\xc3\xb6\xc3\xbc HTTP/1.0\r\n\r\n"
|
||||||
)
|
)
|
||||||
self.assertTrue(b"400 Bad Request" in response)
|
self.assertTrue(response.startswith(b"HTTP/1.0 400 Bad Request"))
|
||||||
|
|
||||||
def test_invalid_header_name(self):
|
def test_invalid_header_name(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -321,4 +321,4 @@ class TestHTTPRequest(DaphneTestCase):
|
||||||
response = self.run_daphne_raw(
|
response = self.run_daphne_raw(
|
||||||
f"GET / HTTP/1.0\r\n{header_name}: baz\r\n\r\n".encode("ascii")
|
f"GET / HTTP/1.0\r\n{header_name}: baz\r\n\r\n".encode("ascii")
|
||||||
)
|
)
|
||||||
self.assertTrue(b"400 Bad Request" in response)
|
self.assertTrue(response.startswith(b"HTTP/1.0 400 Bad Request"))
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
|
|
||||||
def test_fd_endpoint_plugin_installed():
|
|
||||||
# Find the site-packages directory
|
|
||||||
for path in sys.path:
|
|
||||||
if "site-packages" in path:
|
|
||||||
site_packages = Path(path)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise AssertionError("Could not find site-packages in sys.path")
|
|
||||||
|
|
||||||
plugin_path = site_packages / "twisted" / "plugins" / "fd_endpoint.py"
|
|
||||||
assert plugin_path.exists(), f"fd_endpoint.py not found at {plugin_path}"
|
|
||||||
Loading…
Reference in New Issue
Block a user