GithubHelp home page GithubHelp logo

encode / uvicorn Goto Github PK

View Code? Open in Web Editor NEW
7.9K 91.0 680.0 3.14 MB

An ASGI web server, for Python. 🦄

Home Page: https://www.uvicorn.org/

License: BSD 3-Clause "New" or "Revised" License

Python 99.30% Shell 0.70%
python asyncio asgi http http-server

uvicorn's People

Contributors

abersheeran avatar almarklein avatar aminalaee avatar cdeler avatar cknv avatar dependabot[bot] avatar erm avatar euri10 avatar florimondmanca avatar graingert avatar gvbgduh avatar hanaasagi avatar humrochagf avatar imba-tjd avatar iudeen avatar johnthagen avatar josekilo avatar kludex avatar laggardkernel avatar maximilianhurl avatar mgorny avatar rafalp avatar roang-zero1 avatar simonw avatar tiangolo avatar tomchristie avatar vibhu-agarwal avatar vytas7 avatar woile avatar yolley avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uvicorn's Issues

Configurable http parser & event loop.

Eg. support h11, as used in https://github.com/jeamland/guvnor/blob/master/guvnor/asyncio_worker.py

In particular it'd be good to have a pure-python configuration available to us.

If anyone's interested in helping move this forward I'd suggest that a good first approach would be a pull request that removes http_parser, and replaces it with h11. That'll then help us figure out where their interfaces are different, and help us work towards what we'd like the generalized interface to be.

/cc @jeamland

Can't import module

Ive been looking at the example app.py that is in the top dir of the source and came across this line
from uvicorn.broadcast import BroadcastMiddleware
which causes an import error. I can not find where BroadcastMiddleware is defined.

Catch `HttpParserInvalidMethodError` exception

uvicorn==0.1.1 is throwing these errors

uvicorn[7423]: Unhandled exception in event loop
uvicorn[7423]: Traceback (most recent call last):
uvicorn[7423]:   File "uvloop/handles/stream.pyx", line 784, in uvloop.loop.__uv_stream_on_read_impl
uvicorn[7423]:   File "uvloop/handles/stream.pyx", line 563, in uvloop.loop.UVStream._on_read
uvicorn[7423]:   File "/home/web/.virtualenvs/mesh/lib/python3.5/site-packages/uvicorn/protocols/http.py", line 212, in data_received
uvicorn[7423]:     self.request_parser.feed_data(data)
uvicorn[7423]:   File "httptools/parser/parser.pyx", line 193, in httptools.parser.parser.HttpParser.feed_data
uvicorn[7423]: httptools.parser.errors.HttpParserInvalidMethodError: invalid HTTP method

AttributeError: 'uvloop.loop.TCPTransport' object has no attribute 'drain'

Hi there,

First of all, congratulations for Uvicorn — it's truly amazing and pleasant to use!

Today I was messing around with Django 2.0 + Channels and thought about giving Uvicorn a try as a replacement for Daphne.

Although everything seems to work like a charm, I see an AttributeError in my server's log, without this exception surfacing to the browser. It seems to be caused by the following piece of code:

if self.protocol.write_paused:
await self.transport.drain()

Providing some more details below (full traceback + Python package + system details)

Traceback

Not Found: /favicon.ico
Task exception was never retrieved
future: <Task finished coro=<AsgiHandler.__call__() done, defined at /mnt/data/.python-3.6/lib/python3.6/site-packages/channels/http.py:172> exception=AttributeError("'uvloop.loop.TCPTransport' object has no attribute 'drain'",)>
Traceback (most recent call last):
  File "/mnt/data/.python-3.6/lib/python3.6/site-packages/channels/http.py", line 190, in __call__
    await self.handle(body)
  File "/mnt/data/.python-3.6/lib/python3.6/site-packages/asgiref/sync.py", line 110, in __call__
    return await asyncio.wait_for(future, timeout=None)
  File "/usr/local/lib/python3.6/asyncio/tasks.py", line 339, in wait_for
    return (yield from fut)
  File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/mnt/data/.python-3.6/lib/python3.6/site-packages/asgiref/sync.py", line 125, in thread_handler
    return self.func(*args, **kwargs)
  File "/mnt/data/.python-3.6/lib/python3.6/site-packages/channels/http.py", line 226, in handle
    self.send(response_message)
  File "/mnt/data/.python-3.6/lib/python3.6/site-packages/asgiref/sync.py", line 64, in __call__
    return call_result.result()
  File "/usr/local/lib/python3.6/concurrent/futures/_base.py", line 432, in result
    return self.__get_result()
  File "/usr/local/lib/python3.6/concurrent/futures/_base.py", line 384, in __get_result
    raise self._exception
  File "/mnt/data/.python-3.6/lib/python3.6/site-packages/asgiref/sync.py", line 78, in main_wrap
    result = await self.awaitable(*args, **kwargs)
  File "/mnt/data/.python-3.6/lib/python3.6/site-packages/uvicorn/protocols/http.py", line 158, in send
    await self.transport.drain()
AttributeError: 'uvloop.loop.TCPTransport' object has no attribute 'drain'

pip freeze

asgiref==2.3.0
async-timeout==2.0.1
attrs==17.4.0
autobahn==18.4.1
Automat==0.6.0
backcall==0.1.0
cffi==1.11.5
channels==2.1.1
constantly==15.1.0
daphne==2.1.1
decorator==4.3.0
dj-database-url==0.5.0
Django==2.0
djangorestframework==3.8.2
gunicorn==19.8.1
httptools==0.0.11
hyperlink==18.0.0
idna==2.6
incremental==17.5.0
ipython==6.3.1
ipython-genutils==0.2.0
jedi==0.12.0
parso==0.2.0
pexpect==4.5.0
pickleshare==0.7.4
prompt-toolkit==1.0.15
psycopg2-binary==2.7.4
ptyprocess==0.5.2
pycparser==2.18
Pygments==2.2.0
pytz==2017.3
sec==0.2.2
simplegeneric==0.8.1
six==1.11.0
traitlets==4.3.2
Twisted==18.4.0
txaio==2.10.0
uvicorn==0.1.1
uvloop==0.9.1
wcwidth==0.1.7
websockets==4.0.1
whitenoise==3.3.1
zope.interface==4.5.0

System details

  • OS: Ubuntu 16.04 / SourceLair
  • Python version: 3.6.4
  • pip version: 10.0.1

Block of upload file a big file.

 def on_body(self, body: bytes):
       if self.body:
           self.parsing_request.put_message({
               'type': 'http.request',
               'body': self.body,
               'more_body': True
           })
           self.check_pause_reading()
       self.body = body

because of this method, when upload a file bigger than 1M, method check_pause_reading will block
with self.read_paused set to True。

Benchmarking

Given that the raison d'être of asyncio is achieving high concurrency, we should get TechEmpower benchmarks for the most realistic test types (eg. fortune)

Bind to unix domain socket instead of ip address

When running applications like uvicorn behind a reverse proxy like NGINX it is best practice to use a unix domain socket instead of binding to an ip address. This has the benefit of improved security and performance.

This could be implemented the same way as gunicorn does it. If the bind parameter starts with unix:, use a unix domain socket. One caveat is that the socket file will have to be created beforehand and cleaned up afterwards.

Unhandled exception when httptools.parse_url() returns a None path

I encountered the following exception while running an apistar application using uvicorn 0.0.15 on CPython 3.6.4 with SSL enabled:

Unhandled exception in event loop
Traceback (most recent call last):
  File "httptools/parser/parser.pyx", line 241, in httptools.parser.parser.cb_on_url
  File "/home/omer/.local/share/virtualenvs/myproject--RkZn49j/lib/python3.6/site-packages/uvicorn/protocols/http.py", line 278, in on_url
    'path': parsed.path.decode('ascii'),
AttributeError: 'NoneType' object has no attribute 'decode'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "uvloop/handles/stream.pyx", line 784, in uvloop.loop.__uv_stream_on_read_impl
  File "uvloop/handles/stream.pyx", line 563, in uvloop.loop.UVStream._on_read
  File "/home/omer/.pyenv/versions/3.6.4/lib/python3.6/asyncio/sslproto.py", line 514, in data_received
    self._app_protocol.data_received(chunk)
  File "/home/omer/.local/share/virtualenvs/myproject--RkZn49j/lib/python3.6/site-packages/uvicorn/protocols/http.py", line 238, in data_received
    self.request_parser.feed_data(data)
  File "httptools/parser/parser.pyx", line 189, in httptools.parser.parser.HttpParser.feed_data
httptools.parser.errors.HttpParserCallbackError: the on_url callback failed

The exception occurs when the empty HTTP message b' HTTP/1.1\r\n' is provided in https://github.com/encode/uvicorn/blob/master/uvicorn/protocols/http.py#L238

Unfortunately I'm unable to reproduce this problem with requests or curl.
So far the only HTTP client that reproduces this bug is OSQuery 2.11.2 with the remote API enabled. OSQuery 2.8.0 does not present the same problem.

I'm running uvicorn with the following parameters:

uvicorn myproject.app:app \
            --workers=8 \
            --bind=localhost:8080 \
            --keyfile=./server.pem \
            --certfile=./server.pem \
            --ca-certs=./ca.pem \
            --log-level DEBUG \
            --access-logfile=- \
            --do-handshake-on-connect \
            --ciphers TLSv1.2

and OSQuery with the following parameters:

sudo osqueryd --pidfile /tmp/osqueryd.pid --verbose --debug \
    --database_path /tmp/osquery.db/ \
    --tls_hostname localhost:8080 \
    --config_plugin tls \
    --tls_server_certs /usr/local/share/ca-certificates/ca.crt \
    --config_tls_endpoint /collection/configuration \
    --logger_tls_endpoint /collection/log_event \
    --logger_plugin tls \
    --enroll_tls_endpoint /collection/enroll \
    --disable_distributed=false --distributed_plugin=tls --distributed_interval=60 \
    --distributed_tls_read_endpoint /collection/queries \
    --distributed_tls_write_endpoint /collection/results \
    --watchdog_level -1 \
    --enroll_secret_path ./etc/test_enroll_secret.txt

In order to reproduce the problem you'll need to generate your own certificates.
I recommend trustme for that purpose.

I'm going to try to reverse proxy with Nginx next to figure out if OSQuery is at fault here but in any case, the uvicorn should handle malformed (or incomplete? not sure about that) HTTP requests more gracefully.

.serve() interface

We should expose a plain python .serve(host, port) style interface, for when you don't want fully-fledged gunicorn process management.

Logging does not work

None of my apistar app's access logging or other logging in application code that works with daphne or gunicorn works here. It seems like logging may not be implemented. Please advise.

Do not hardcode uvloop into UvicornServer.run

Currently asyncio event loop is replaced in UvicornServer.run method:

    def run(self, app, host, port):
        asyncio.get_event_loop().close()
        asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
        loop = asyncio.get_event_loop()

Because of that, there is no way for app to do initialization using uvicorn event loop, because before running the server, existing event loop is closed and replaced by new one.

I thin, event loop policy should be change only if uvicorn is the main entry point, for example uvicorn.main.run could do that. Otherwise, app using uvicorn should take care changing event loop policy.

Pipelining support in `httptools` implementation

We've temporarily dropped pipelining support from the httptools implementation, although everythings in place in order to support it. Need to:

Keep track of queued request/response cycles if a new cycle starts before the existing one has finished. Callback to the protocol to start the next cycle in the queue if needed.

Error using websockets==4.0.1

Hi,

I was trying to run this example using uvicorn + websockets 4.0.1 (latest version):

async def chat_server(message, channels):
    """
    ASGI-style 'Hello, world' application.
    """
    if message['channel'] == 'websocket.connect':
        await channels['reply'].send({'accept': True})

And I get this error after sending the accept message.

Starting worker [9001] serving at: 0.0.0.0:8000
Task exception was never retrieved
future: <Task finished coro=<reader() done, defined at /home/vinicius/projects/dealer/venv/lib/python3.6/site-packages/uvicorn/protocols/websocket.py:65> exception=TypeError('An asyncio.Future, a coroutine or an awaitable is required',)>
Traceback (most recent call last):
  File "/home/vinicius/projects/dealer/venv/lib/python3.6/site-packages/uvicorn/protocols/websocket.py", line 72, in reader
    data = await protocol.recv()
  File "/home/vinicius/projects/dealer/venv/lib/python3.6/site-packages/websockets/protocol.py", line 309, in recv
    loop=self.loop, return_when=asyncio.FIRST_COMPLETED)
  File "/usr/lib/python3.6/asyncio/tasks.py", line 311, in wait
    fs = {ensure_future(f, loop=loop) for f in set(fs)}
  File "/usr/lib/python3.6/asyncio/tasks.py", line 311, in <setcomp>
    fs = {ensure_future(f, loop=loop) for f in set(fs)}
  File "/usr/lib/python3.6/asyncio/tasks.py", line 526, in ensure_future
    raise TypeError('An asyncio.Future, a coroutine or an awaitable is '
TypeError: An asyncio.Future, a coroutine or an awaitable is required

It works fine with websockets 3.4.0

I was looking into it and I noticed that in the protocol.py (from websockets) the variable transfer_data_task is not initialized so a None is being added to the queue of events causing the error.

It could be a bug in websockets 4.0.* or they have changed the logic and uvicorn is not compatible anymore.

Broadcast functionality

Implementation using redis pub/sub.

Interface along these lines:

    def ws_connected(message, channels):
        channels['reply'].send({'accept': True})
        channels['groups'].send({
            'group': 'chat',
            'add': channels['reply'].name
        })

    def ws_receive(message, channels):
        channels['groups'].send({
            'group': 'chat',
            'send': message['text']
        })

    def ws_disconnect(message, channels):
        channels['groups'].send({
            'group': 'chat',
            'discard': channels['reply'].name
        })

uvicorn.run.run function shadows uvicorn.run module

uvicorn/__init__.py has this line:

from uvicorn.run import run

This line shadows uvicorn.run module and for example, I can't import module like this import uvicorn.run, because it gives function, not module. But on the other hand, from uvicorn.run import UvicornServer.

PyPy Support

Hi folks, have you benchmarked this on PyPy? Just curious as to whether using the standard asyncio implementation under PyPy would be faster than uvloop due to thunking across the Cython FFI.

Gunicorn deployments timeout option does not seem to work properly

uvicorn avilpage.asgi --log-level debug --bind 0.0.0.0:8000 --workers 2 --timeout 15

When uvicorn is started with above command, workers doesn't restart after 15 seconds. It doesn't seem to work for t>14.

For t<=14, it works.

[2018-06-01 11:16:06 +0530] [9402] [INFO] Booting worker with pid: 9402
[2018-06-01 11:16:06 +0530] [9403] [INFO] Booting worker with pid: 9403
[2018-06-01 11:16:06 +0530] [9385] [DEBUG] 2 workers
[2018-06-01 11:16:20 +0530] [9385] [CRITICAL] WORKER TIMEOUT (pid:9402)
[2018-06-01 11:16:20 +0530] [9385] [CRITICAL] WORKER TIMEOUT (pid:9403)
[2018-06-01 11:16:21 +0530] [9402] [INFO] Error while closing socket [Errno 9] Bad file descriptor
[2018-06-01 11:16:21 +0530] [9402] [INFO] Worker exiting (pid: 9402)
[2018-06-01 11:16:21 +0530] [9403] [INFO] Error while closing socket [Errno 9] Bad file descriptor
[2018-06-01 11:16:21 +0530] [9403] [INFO] Worker exiting (pid: 9403)
[2018-06-01 11:16:21 +0530] [9806] [INFO] Booting worker with pid: 9806
[2018-06-01 11:16:22 +0530] [9385] [DEBUG] 1 workers
[2018-06-01 11:16:22 +0530] [9807] [INFO] Booting worker with pid: 9807
[2018-06-01 11:16:22 +0530] [9385] [DEBUG] 2 workers

Gunicorn deployments with `--preload` not working properly.

Use case: you want to launch an asgi app to a 128 core machine with 128 processes
Problem: 128xprocess boot time takes a while, in dockered environments (like k8s) this becomes an issue, quick boots mean quick deploys
Preload: it takes ~100 times less boot time
Error: RuntimeError: Event loop is closed

Somewhat related: #61

The reason is gunicorn loads the app once and forks from there when preloading, so it seems every fork gets a different loop from the one that preloading got for the asgi app.

Mach9

I forked Sanic and created Mach9.
Mach9 is a web application framework based on ASGI.
Mach9 can be integrated Uvicorn.

TypeError while disconnecting socket connections

Uvicorn sometimes throws this error when client tries to disconnect. This doesn't seem to happen when daphne is used.

Task exception was never retrieved
future: <Task finished coro=<websocket_session() done, defined at /home/chillar/.virtualenvs/mesh/lib/python3.6/site-packages/uvicorn/protocols/websocket.py:31> exception=TypeError("'<=' not supported between instances of 'int' and 'NoneType'",)>
Traceback (most recent call last):
  File "/home/chillar/.virtualenvs/mesh/lib/python3.6/site-packages/uvicorn/protocols/websocket.py", line 40, in websocket_session
    data = await protocol.recv()
  File "/home/chillar/.virtualenvs/avilpage.com/lib/python3.6/site-packages/websockets/protocol.py", line 323, in recv
    raise ConnectionClosed(self.close_code, self.close_reason)
  File "/home/chillar/.virtualenvs/avilpage.com/lib/python3.6/site-packages/websockets/exceptions.py", line 147, in __init__
    if 3000 <= code < 4000:
TypeError: '<=' not supported between instances of 'int' and 'NoneType'

Uvicorn 0.2.0 package missing README.md

  Using cached https://files.pythonhosted.org/packages/c7/a7/92333ff7e11f703af974485247ae1231bed96d3e9b8e5a48f4009d985761/uvicorn-0.2.0.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/private/var/folders/4g/1rsbx7zd74z2pz2x_qhbhwlm0004z1/T/pip-install-92dplo46/uvicorn/setup.py", line 44, in <module>
        long_description=get_long_description(),
      File "/private/var/folders/4g/1rsbx7zd74z2pz2x_qhbhwlm0004z1/T/pip-install-92dplo46/uvicorn/setup.py", line 23, in get_long_description
        return open('README.md', 'r').read()
    FileNotFoundError: [Errno 2] No such file or directory: 'README.md'

I believe, include those to MANIFEST could help (not sure, I always had troubles with python packaging)

Use 'body' in requests.

First frame of any body data could fill 'body' rather than create a body queue.
This'd be nicer for debugging incoming request messages, as some or all of the body data will be visible in the http.request message.

Websocket timeout configuration?

Daphne has config options for websocket timeout

  --websocket_timeout WEBSOCKET_TIMEOUT
                        Maximum time to allow a websocket to be connected. -1
                        for infinite.
  --websocket_connect_timeout WEBSOCKET_CONNECT_TIMEOUT
                        Maximum time to allow a connection to handshake. -1
                        for infinite

So server never closes connections by default.

I am trying to use uvicorn to run django asgi with this command.

uvicorn foo.asgi --workers 5 --log-level debug --bind 0.0.0.0:9000 --timeout 14400 --graceful-timeout 14400

Unfortunately, websockets are getting closed after a minute or so. Is there a way to configure this?

Pipelining

Currently responses could come back out of order.

Contribution guidelines

It may be a good idea to establish contribution guidelines for this project in order to help anyone that is interested in improving things but unsure of how to actually engage the process of proposing changes or submitting PRs.

I am a bit unclear on how to approach some of the existing issues, and it would be helpful if there were a process in place to organize/prioritize tasks that need to be done as well as to identify potential blockers.

Perhaps something similar to what Channels does? It seems like a good example of how this could be handled.

Support `Expect: 100-Continue`

  • Deal with Expect: 100-Continue headers gracefully, by only sending if the request body is read prior to sending the response headers.

Support channel layers

Allow for unsticky websockets, by supporting channel layers.

  • A consumer callable that routes some or all channels to a channel layer.
  • A worker that pulls messages off a channel layer.

Sanic compatibility?

Is this software compatible with sanic, or does sanic need asgi interface to work with this?

windows support

Can uvicorn support windows?
I am develops in windows, and want to use uvicorn.

Interface work...

  • Support non-coroutine consumer functions? No, but perhaps an equivelent sync version of the messaging interface could be valid for threaded-concurrency applications.
  • Possible that send() should just be a plain function, buffers the output? No: server should handle calling await transport.drain() when required.
  • Ensure buffering exceptions, closes all properly accounted for.
  • Support a .channels = [...] attribute on the consumer callable.
  • Expose exc_info?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.