Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update wsgi to support big body #635

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
075ac7e
update wsgi to support big body
abersheeran Apr 14, 2020
f9b47a3
Merge branch 'master' of https://github.com/abersheeran/uvicorn; bran…
abersheeran Apr 17, 2020
f44daba
fix flake8 check
abersheeran Apr 17, 2020
7d522a9
update to threading.Event
abersheeran May 3, 2020
57a33d3
Merge branch 'master' into master
abersheeran May 3, 2020
3be85b6
Update test-suite.yml
tomchristie May 4, 2020
1e2d7e7
Added asgi version and spec_version to scope (#597)
euri10 May 4, 2020
8fed0e2
Don't override the root logger (#674)
stchris May 15, 2020
7604771
Fix typo. (#676)
Asday May 17, 2020
65cb5ed
Document default backlog setting (#682)
ipmb May 27, 2020
0006fa6
Add --app-dir option for running uvicorn from any location (#619)
yezyilomo Jun 9, 2020
ccbfb9f
Removing iocp mentions from documentation (#692)
Bloodielie Jun 10, 2020
2a47d09
Release version 0.11.6 (#705)
tiangolo Jul 17, 2020
325983e
Brings back windows testing to CI (#685)
euri10 Jul 24, 2020
c982cad
Disallow invalid header characters (#725)
tomchristie Jul 28, 2020
7ef8e2a
Quote path component before logging (#724)
tomchristie Jul 28, 2020
5159862
Corrected --proxy-headers client ip/host when using a unix socket (#636)
euri10 Jul 28, 2020
4eddfdf
Version 0.11.7 (#726)
tomchristie Jul 28, 2020
dfe9c9e
Update CHANGELOG.md
tomchristie Jul 29, 2020
77c36f6
Fix crash when --interface is wsgi (#730)
mpaolini Jul 30, 2020
69c7126
Update 0.11.7 changelog (#732)
florimondmanca Jul 30, 2020
1ced963
Get the request.client under case uvicorn is run with a fd or a unix …
euri10 Jul 31, 2020
8a37f8e
Version 0.11.8 (#731)
florimondmanca Jul 31, 2020
e7d2acf
Added Isuue template based on the one from httpx (#735)
euri10 Jul 31, 2020
912ecaa
Move the dir (#737)
euri10 Aug 4, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/ISSUE_TEMPLATE/1-question.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
name: Question
about: Ask a question
---

### Checklist

<!-- To help keep this issue tracker clean and focused, please make sure you tried *all* the following resources before submitting your question. -->

- [ ] I searched the [Uvicorn documentation](https://www.uvicorn.org/) but couldn't find what I'm looking for.
- [ ] I looked through similar issues on GitHub, but didn't find anything.
- [ ] I looked up "How to do ... in Uvicorn" on a search engine and didn't find any information.
- [ ] I asked the [community chat](https://gitter.im/encode/community) for help.

### Question

<!-- Please ask your question here. -->
53 changes: 53 additions & 0 deletions .github/ISSUE_TEMPLATE/2-bug-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
name: Bug report
about: Report a bug to help improve this project
---

### Checklist

<!-- Please make sure you check all these items before submitting your bug report. -->

- [ ] The bug is reproducible against the latest release and/or `master`.
- [ ] There are no similar issues or pull requests to fix it yet.

### Describe the bug

<!-- A clear and concise description of what the bug is. -->

### To reproduce

<!-- Provide a *minimal* example with steps to reproduce the bug locally.

NOTE: try to keep any external dependencies *at an absolute minimum* .
In other words, remove anything that doesn't make the bug go away.

-->

### Expected behavior

<!-- A clear and concise description of what you expected to happen. -->

### Actual behavior

<!-- A clear and concise description of what actually happens. -->

### Debugging material

<!-- Any tracebacks, screenshots, etc. that can help understanding the problem.

NOTE:
- Please list tracebacks in full (don't truncate them).
- If relevant, consider turning on DEBUG or TRACE logs for additional details (see the Logging section on https://www.uvicorn.org/settings/ specifically the `log-level` flag).
- Consider using `<details>` to make tracebacks/logs collapsible if they're very large (see https://gist.github.com/ericclemmons/b146fe5da72ca1f706b2ef72a20ac39d).
-->

### Environment

- OS / Python / Uvicorn version: just run `uvicorn --version`
- The exact command you're running uvicorn with, all flags you passed included. If you run it with gunicorn please do the same. If there is a reverse-proxy involved and you cannot reproduce without it please give the minimal config of it to reproduce.

### Additional context

<!-- Any additional information that can help understanding the problem.

Eg. linked issues, or a description of what you were trying to achieve. -->
33 changes: 33 additions & 0 deletions .github/ISSUE_TEMPLATE/3-feature-request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: Feature request
about: Suggest an idea for this project.
---

### Checklist

<!-- Please make sure you check all these items before submitting your feature request. -->

- [ ] There are no similar issues or pull requests for this yet.
- [ ] I discussed this idea on the [community chat](https://gitter.im/encode/community) and feedback is positive.

### Is your feature related to a problem? Please describe.

<!-- A clear and concise description of what you are trying to achieve.

Eg "I want to be able to [...] but I can't because [...]". -->

## Describe the solution you would like.

<!-- A clear and concise description of what you would want to happen.

For API changes, try to provide a code snippet of what you would like the API to look like.
-->

## Describe alternatives you considered

<!-- Please describe any alternative solutions or features you've considered to solve
your problem and why they wouldn't solve it. -->

## Additional context

<!-- Provide any additional context, screenshots, tracebacks, etc. about the feature here. -->
11 changes: 7 additions & 4 deletions .github/workflows/test-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,27 @@
name: Test Suite

on:
push:
branches: ["master"]
pull_request:
branches: ["master"]

jobs:
tests:
name: "Python ${{ matrix.python-version }}"
runs-on: "ubuntu-latest"

name: "Python ${{ matrix.python-version }} ${{ matrix.os }}"
runs-on: "${{ matrix.os }}"
strategy:
matrix:
python-version: ["3.6", "3.7", "3.8"]

os: [windows-latest, ubuntu-latest]
steps:
- uses: "actions/checkout@v2"
- uses: "actions/setup-python@v1"
with:
python-version: "${{ matrix.python-version }}"
- name: "Install dependencies"
run: "scripts/install"
shell: bash
- name: "Run tests"
run: "scripts/test"
shell: bash
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Change Log

## 0.11.8 - 2020-07-30

* Fix a regression that caused Uvicorn to crash when using `--interface=wsgi`. (Pull #730)
* Fix a regression that caused Uvicorn to crash when using unix domain sockets. (Pull #729)

## 0.11.7 - 2020-28-07

* SECURITY FIX: Prevent sending invalid HTTP header names and values. (Pull #725)
* SECURITY FIX: Ensure path value is escaped before logging to the console. (Pull #724)
* Fix `--proxy-headers` client IP and host when using a Unix socket. (Pull #636)

## 0.11.6

* Fix overriding the root logger.

## 0.11.5

* Revert "Watch all files, not just .py" due to unexpected side effects.
Expand Down
7 changes: 5 additions & 2 deletions docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Options:
--workers INTEGER Number of worker processes. Defaults to the
$WEB_CONCURRENCY environment variable if
available. Not valid with --reload.
--loop [auto|asyncio|uvloop|iocp]
--loop [auto|asyncio|uvloop]
Event loop implementation. [default: auto]
--http [auto|h11|httptools] HTTP protocol implementation. [default:
auto]
Expand Down Expand Up @@ -87,6 +87,9 @@ Options:
[default: TLSv1]
--header TEXT Specify custom default HTTP response headers
as a Name:Value pair
--app-dir TEXT Look for APP in the specified directory, by
adding this to the PYTHONPATH. Defaults to
the current working directory.
--help Show this message and exit.
```

Expand Down Expand Up @@ -255,7 +258,7 @@ To run uvicorn with https, a certificate and a private key are required.
The recommended way to get them is using [Let's Encrypt][letsencrypt].

For local development with https, it's possible to use [mkcert][mkcert]
to generate a valid certificat and private key.
to generate a valid certificate and private key.

```bash
$ uvicorn example:app --port 5000 --ssl-keyfile=./key.pem --ssl-certfile=./cert.pem
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Options:
--workers INTEGER Number of worker processes. Defaults to the
$WEB_CONCURRENCY environment variable if
available. Not valid with --reload.
--loop [auto|asyncio|uvloop|iocp]
--loop [auto|asyncio|uvloop]
Event loop implementation. [default: auto]
--http [auto|h11|httptools] HTTP protocol implementation. [default:
auto]
Expand Down
4 changes: 2 additions & 2 deletions docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ $ pip install uvicorn[watchgodreload]

## Implementation

* `--loop <str>` - Set the event loop implementation. The uvloop implementation provides greater performance, but is not compatible with Windows or PyPy. But you can use IOCP in windows. **Options:** *'auto', 'asyncio', 'uvloop', 'iocp'.* **Default:** *'auto'*.
* `--loop <str>` - Set the event loop implementation. The uvloop implementation provides greater performance, but is not compatible with Windows or PyPy. **Options:** *'auto', 'asyncio', 'uvloop'.* **Default:** *'auto'*.
* `--http <str>` - Set the HTTP protocol implementation. The httptools implementation provides greater performance, but it not compatible with PyPy, and requires compilation on Windows. **Options:** *'auto', 'h11', 'httptools'.* **Default:** *'auto'*.
* `--ws <str>` - Set the WebSockets protocol implementation. Either of the `websockets` and `wsproto` packages are supported. Use `'none'` to deny all websocket requests. **Options:** *'auto', 'none', 'websockets', 'wsproto'.* **Default:** *'auto'*.
* `--lifespan <str>` - Set the Lifespan protocol implementation. **Options:** *'auto', 'on', 'off'.* **Default:** *'auto'*.
Expand Down Expand Up @@ -71,7 +71,7 @@ connecting IPs in the `forwarded-allow-ips` configuration.

* `--limit-concurrency <int>` - Maximum number of concurrent connections or tasks to allow, before issuing HTTP 503 responses. Useful for ensuring known memory usage patterns even under over-resourced loads.
* `--limit-max-requests <int>` - Maximum number of requests to service before terminating the process. Useful when running together with a process manager, for preventing memory leaks from impacting long-running processes.
* `--backlog <int>` - Maximum number of connections to hold in backlog. Relevant for heavy incoming traffic.
* `--backlog <int>` - Maximum number of connections to hold in backlog. Relevant for heavy incoming traffic. **Default:** *2048*

## Timeouts

Expand Down
19 changes: 19 additions & 0 deletions requirements_windows.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
click
h11

# Optional
websockets==8.*
wsproto==0.13.*

# Testing
autoflake
black
codecov
flake8
isort
pytest
pytest-cov
requests

# Efficient debug reload
watchgod>=0.6,<0.7
10 changes: 8 additions & 2 deletions scripts/install
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
#!/bin/sh -e
#!/usr/bin/env bash

set -e

# Use the Python executable provided from the `-p` option, or a default.
[ "$1" = "-p" ] && PYTHON=$2 || PYTHON="python3"

REQUIREMENTS="requirements.txt"
if [ "$OSTYPE" = "linux-gnu" ]; then
REQUIREMENTS="requirements.txt"
elif [ "$OSTYPE" = "msys" ]; then
REQUIREMENTS="requirements_windows.txt"
fi
VENV="venv"

set -x
Expand Down
48 changes: 47 additions & 1 deletion tests/middleware/test_wsgi.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,44 @@
import sys
import asyncio
from tempfile import TemporaryFile

import pytest

from tests.client import TestClient
from uvicorn.middleware.wsgi import WSGIMiddleware
from uvicorn.middleware.wsgi import WSGIMiddleware, Body


def test_body():
recv_event = asyncio.Event()
body = Body(recv_event)
body.write(
b"""This is a body test.
Why do this?
To prevent memory leaks.
And cancel pre-reading.
Newline.0
Newline.1
Newline.2
Newline.3
"""
)
body.feed_eof()
assert body.readline() == b"This is a body test.\n"
assert body.readline(6) == b"Why do"
assert body.readline(20) == b" this?\n"

assert body.readlines(2) == [
b"To prevent memory leaks.\n",
b"And cancel pre-reading.\n",
]
for index, line in enumerate(body):
assert line == b"Newline." + str(index).encode("utf8") + b"\n"
if index == 1:
break
assert body.readlines() == [
b"Newline.2\n",
b"Newline.3\n",
]


def hello_world(environ, start_response):
Expand Down Expand Up @@ -62,6 +97,17 @@ def test_wsgi_post():
assert response.text == '{"example": 123}'


def test_wsgi_post_big_file():
app = WSGIMiddleware(echo_body)
client = TestClient(app)
file = TemporaryFile()
for num in range(1000000):
file.write(str(num).encode("utf8"))
response = client.post("/", files={"file": file})
assert response.status_code == 200
assert response.content


def test_wsgi_exception():
# Note that we're testing the WSGI app directly here.
# The HTTP protocol implementations would catch this error and return 500.
Expand Down
26 changes: 26 additions & 0 deletions tests/protocols/test_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -674,3 +674,29 @@ def test_supported_upgrade_request(protocol_cls):
protocol.data_received(UPGRADE_REQUEST)

assert b"HTTP/1.1 426 " in protocol.transport.buffer


async def asgi3app(scope, receive, send):
pass


def asgi2app(scope):
async def asgi(receive, send):
pass

return asgi


asgi_scope_data = [
(asgi3app, {"version": "3.0", "spec_version": "2.1"}),
(asgi2app, {"version": "2.0", "spec_version": "2.1"}),
]


@pytest.mark.parametrize("asgi2or3_app, expected_scopes", asgi_scope_data)
@pytest.mark.parametrize("protocol_cls", HTTP_PROTOCOLS)
def test_scopes(asgi2or3_app, expected_scopes, protocol_cls):
protocol = get_connected_protocol(asgi2or3_app, protocol_cls,)
protocol.data_received(SIMPLE_GET_REQUEST)
protocol.loop.run_one()
assert expected_scopes == protocol.scope.get("asgi")