GithubHelp home page GithubHelp logo

pallets / quart Goto Github PK

View Code? Open in Web Editor NEW
2.6K 28.0 140.0 2.33 MB

An async Python micro framework for building web applications.

Home Page: https://quart.palletsprojects.com

License: MIT License

Python 100.00%
asyncio python http-server asgi quart

quart's People

Contributors

0az avatar andrewshadura avatar arminweigl avatar arseniybanayev avatar arusahni avatar astremy avatar briancappello avatar browniebroke avatar crood58 avatar dependabot[bot] avatar etiennepelletier avatar gilbertyoder avatar jaimelennox avatar jay-tuckey avatar jeamland avatar kurtmckee avatar l1f avatar laggardkernel avatar lun-4 avatar masipcat avatar matham avatar pgjones avatar potomak avatar pszpetkowski avatar sanderfoobar avatar tharvik avatar touilleman avatar unicodex avatar white-gecko avatar wwwjfy 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

quart's Issues

Multipart form data patch improvement

Hi I submitted a patch a while back that fixed problems with multi part form data for uploading files I needed to improve that patch to handle some different situations mostly the fact that sometimes the content length header is missing also sometimes Content-Length is a str not an int so to deal with these cases I have made the following patch which I use from my private pypi repo

diff --git a/quart/__about__.py b/quart/__about__.py
index ef72cc0..4ca39e7 100644
--- a/quart/__about__.py
+++ b/quart/__about__.py
@@ -1 +1 @@
-__version__ = '0.8.1'
+__version__ = '0.8.2'
diff --git a/quart/wrappers/request.py b/quart/wrappers/request.py
index 09eea94..4658097 100644
--- a/quart/wrappers/request.py
+++ b/quart/wrappers/request.py
@@ -220,10 +220,9 @@ class Request(BaseRequestWebsocket, JSONMixin):
                 for value in values:
                     self._form.add(key, value)
         elif content_type == 'multipart/form-data':
-            limit = self.headers['content-length']
             field_storage = FieldStorage(
                 io.BytesIO(raw_data), headers=self.headers,
-                environ={'REQUEST_METHOD': 'POST'}, limit=limit,
+                environ={'REQUEST_METHOD': 'POST'}, limit=len(raw_data),
             )
             for key in field_storage:  # type: ignore
                 field_storage_key = field_storage[key]
diff --git a/setup.py b/setup.py
index bc81faf..f346097 100644
--- a/setup.py
+++ b/setup.py
@@ -27,7 +27,7 @@ INSTALL_REQUIRES = [
 ]
 
 setup(
-    name='Quart',
+    name='quart',
     version=about['__version__'],
     python_requires='>=3.7.0',
     description="A Python ASGI web microframework with the same API as Flask",

write_any_response bug always returns 200 status

The line
bytesmod(b"HTTP/1.1 %s %s\r\n", (status_bytes, response.reason))
returns a string like
b'HTTP/1.1 HTTPStatus.PARTIAL_CONTENT \r\n'
but should be
b'HTTP/1.1 206 \r\n'

Using
bytesmod(b"HTTP/1.1 %d %s\r\n", (response.status_code, response.reason))
returns the correct result allowing partial content to actually go across as a 206 vs 200.

How to consume JWT token?

Looking for some guidance or example on how to consume JWT token with Quart? is there a extension that works with quart?

flask_ext example gives error: TypeError: isinstance() arg 2 must be a type or tuple of types

I'm trying to change my flask project to a quart project.

The project uses Flask-Login. To begin simple, i'm trying to run the flask_ext example.

I'm doing this in my virtual env. (this already runs my to Quart converted project successfully without Flask-Login.

Running the flask_ext example gives this error:

Running commands:
set QUART_APP=flask_ext:app
quart run

import quart.flask_patch
File "c:\werk\modules uitproberen\quart\venv\lib\site-packages\quart\flask_patch\__init__.py", line 5, in <module>
 patch_all()
File "c:\werk\modules uitproberen\quart\venv\lib\site-packages\quart\flask_patch\_patch.py", line 117, in patch_all
 _patch_asyncio()
File "c:\werk\modules uitproberen\quart\venv\lib\site-packages\quart\flask_patch\_patch.py", line 26, in _patch_asyncio
 if not isinstance(current_policy, target_policy):
TypeError: isinstance() arg 2 must be a type or tuple of types

Any ideas what could be wrong?

Kind regards,

Extra info:
Python version: 3.7.0
pip freeze:

aiofiles==0.4.0
asyncio==3.4.3
blinker==1.4
Click==7.0
Flask==1.0.2
Flask-Login==0.4.1
h11==0.8.1
h2==3.0.1
hpack==3.0.0
Hypercorn==0.4.3
hyperframe==5.1.0
itsdangerous==1.1.0
Jinja2==2.10
MarkupSafe==1.1.0
multidict==4.5.2
numpy==1.15.4
pandas==0.23.4
passlib==1.7.1
python-dateutil==2.7.5
pytoml==0.1.20
pytz==2018.7
Quart==0.7.1
raven==6.10.0
six==1.12.0
sortedcontainers==2.1.0
typing-extensions==3.6.6
Werkzeug==0.14.1
wsproto==0.12.0

[Question] Unable to get Quart working with Docker

Hi there,

I am trying to get started with Quart using a Docker container.

I created a simple Dockerfile called api.dockerfile as follows:

FROM python:3.7-alpine
COPY requirements.txt /
RUN pip install -r /requirements.txt
COPY . /app
WORKDIR /app
EXPOSE 5000

Within my requirements.txt I have a single entry called quart.

I have a file called app.py taken from the documentation's Getting Started section:

from quart import Quart
  
app = Quart(__name__)

@app.route('/')
async def hello():
    return 'hello'

app.run()

I am running the Dockerfile using docker-compose. This is my docker-compose.yml:

version: '3'
services:
  api:
    build:
      context: .
      dockerfile: api.dockerfile
    image: my_docker_quart_compose:latest
    volumes:
      - .:/app
    command: python app.py
    ports:
      - "5000:5000"

When I run docker-compose up, the sequence gets stuck as follows (api-test is my current directory):

Creating network "api-test_default" with the default driver
Creating api-test_api_1 ... done
Attaching to api-test_api_1

My machine is listening at port 5000, but I get an empty response from the server.

I've tried the following with no luck:

Quart works perfectly without problems locally.

I am not sure if I am missing something. Your input is much appreciated!

negative indices in session dictionary

Hi,

I've written a simple shopping cart in session.

When i'm trying to remove items from the cart it goes wrong. With normal iteration through the dictionary, it doesn't delete all items when i ask it to.
Playing with it, i came to the solution below. It seems that the range of the cart items begins at a negative index.

Am i seeing this wrong ? Or am i doing something wrong? Or is it just a bug?

cart_items = session["cart"]
for index in range(-1*len(cart_items),0):
    if remove_all:
        session['cart'].remove(cart_items[index])
    else:
        if str(cart_items[index]) == identifier:
            session['cart'].remove(cart_items[index])
            break

cheers,

reading from redis queue and sending data to webpage

I got quart websocket example running on Python 3.6.4. Now I want to read data from a redis queue and send it to my webpage.

I also will receive data from the web page and call functions within a class or if easier, put it into an outgoing redis queue.

How can I best implement it in quart server?

I would very much appreciate your help in this matter

allow teardown decorator to wrap async function to clean up consumer producer queues

Hi I have two asyncio consumer/producer queues that I need to clean up with an async function

I would like to be able to do this

@app.teardown_appcontext
async def teardown(response_or_exc):
    try:
        await vision_queue.stop()
        await webhook_queue.stop()
        while not vision_queue.stopped or not webhook_queue.stopped:
            pass
    except KeyboardInterrupt:
        pass

so I have created a patch for quart

diff --git a/quart/__about__.py b/quart/__about__.py
index ef72cc0..4ca39e7 100644
--- a/quart/__about__.py
+++ b/quart/__about__.py
@@ -1 +1 @@
-__version__ = '0.8.1'
+__version__ = '0.8.2'
diff --git a/quart/app.py b/quart/app.py
index aeab04b..a067a61 100644
--- a/quart/app.py
+++ b/quart/app.py
@@ -1285,7 +1285,10 @@ class Quart(PackageStatic):
     async def do_teardown_appcontext(self, exc: Optional[BaseException]) -> None:
         """Teardown the app (context), calling the teardown functions."""
         for function in self.teardown_appcontext_funcs:
-            function(exc)
+            if asyncio.iscoroutinefunction(function):
+                await function(exc)
+            else:
+                function(exc)
         await appcontext_tearing_down.send(self, exc=exc)
 
     def app_context(self) -> AppContext:
diff --git a/setup.py b/setup.py
index bc81faf..f346097 100644
--- a/setup.py
+++ b/setup.py
@@ -27,7 +27,7 @@ INSTALL_REQUIRES = [
 ]
 
 setup(
-    name='Quart',
+    name='quart',
     version=about['__version__'],
     python_requires='>=3.7.0',
     description="A Python ASGI web microframework with the same API as Flask",

ssl connection SSL_ERROR_SYSCALL

I tried quart in docker by alpine3.7 with python 3.6.5, and I added --with-ssl when I install python.(seems no ssl in python3)
using the http2.py example, it's ok to run application:

/home/quart # python http2.py 
Running on https://127.0.0.1:5000 (CTRL + C to quit)

but once I accessed it by curl, error occured:

$ curl --http2 -v  "https://127.0.0.1:5000/"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
  CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to 127.0.0.1:5000 
* Closing connection 0
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to 127.0.0.1:5000

It seems that connection already setup, but it was closed by quart when client sent 'Client hello'.
Spending a lot of time, I still not fix it, so ask for a help :(

RuntimeError: Working outside of application context

I don't understand why I'm still getting this error even after adding the proper context as per documentation

@app.route('/')
async def pdf():
	asyncio.create_task(sendMail())
	return 'Done'
async def sendMail():
        async with app.app_context():
		print('sending mail')
		msg = Message(
			'Message',
			recipients=['[email protected]']
		)
		mail.send(msg)

Certbot certificate installation > running Quart on https

Hi,

It may be a bit off topic, but i can't find an answer on the net... Sorry if this is a noob question.

Has anybody installed a certificate with certbot for a Quart/Hypercorn server?
I have a converted project from Flask to Quart. In Flask i used an Apache2 webserver. Installing the certificate was very easy.

I made a new server and i'm trying certbot with webroot right now. This is giving me an error.

sudo certbot certonly
Saving debug log to /var/log/letsencrypt/letsencrypt.log

How would you like to authenticate with the ACME CA?


1: Apache Web Server plugin - Beta (apache)
2: Spin up a temporary webserver (standalone)
3: Place files in webroot directory (webroot)


Select the appropriate number [1-3] then [enter] (press 'c' to cancel): c
Could not choose appropriate plugin: authenticator could not be determined or is not installed
authenticator could not be determined or is not installed
ubuntu@ip-172-xx-31-4:$ sudo -s
root@ip-172-31-xx-4:
# sudo certbot certonly
Saving debug log to /var/log/letsencrypt/letsencrypt.log

How would you like to authenticate with the ACME CA?


1: Apache Web Server plugin - Beta (apache)
2: Spin up a temporary webserver (standalone)
3: Place files in webroot directory (webroot)


Select the appropriate number [1-3] then [enter] (press 'c' to cancel): 3
Plugins selected: Authenticator webroot, Installer None
Please enter in your domain name(s) (comma and/or space separated) (Enter 'c'
to cancel): makemesmile.nl
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for xxxx.nl
Input the webroot for xxxxx.nl: (Enter 'c' to cancel): /var/www/
Waiting for verification...
Cleaning up challenges
Failed authorization procedure. makemesmile.nl (http-01): urn:ietf:params:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from

http://xxxxx.nl/.well-known/acme-challenge/6sXI6Av

Do i need to do something with a route for '/.well-known/'? Or is it something completely different?

Websocket guidance needed

I've got the echo websocket tutorial working fine with a javascript client, but I'm lost as to how to go forward

(Other than learning Twisted I'm pretty new to python web libraries and async programming, so I wouldn't be surprised if this is just a lack of knowledge on my part rather than lack of Quart documentation)

I want my browser client to provide some parameters to the server initially, to identify what types of data that client is subscribing to, and trigger the Quart application to begin fetching and caching that data from another server (paginated REST API). As that data becomes cached locally I want to forward it via the websocket to the client... and really to any other websocket clients subscribed for the same kind of data.

Any guidance via examples or references to learning materials would be appreciated!

oidc clients

Can we use the following extensions (Flask-OIDC and Flask-pyoidc) with quart? I want to use oidc provider for authentication and want to know if this extensions are supported with patching.

Question about send_file

Hi,

I'm trying to generate an excel file in memory and then make it available to download in the browser.
I looked up how to do that in flask and came to the following code:

 output = io.BytesIO()
    writer = pd.ExcelWriter(output, engine='xlsxwriter')

    s = pd.DataFrame(statistics.get_all_values_for_download(survey_id))
    s.to_excel(writer, sheet_name='Sheet1')
    writer.save()
    output.seek(0)
    survey = Survey.get(survey_id)
  
    filename = survey.description + '-' + survey.title + datetime.datetime.now().strftime("%d-%b %H:%M")
    return await send_file(output, attachment_filename='{}.xlsx'.format(filename), as_attachment=True)

This is giving the error:

TypeError expected str, bytes or os.PathLike object, not _io.BytesIO

Reducing it to a simpler form: save the file to disk and serving it (and maybe removing it with a cronjob) seems to work, but the filename isn't ok.

` filename = survey.description + '-' + survey.title +'.xlsx'

writer = pd.ExcelWriter('./static/xlsfiles/'+filename, engine='xlsxwriter')

all_votes = await statistics.get_all_values_for_download(survey_id)
s = pd.DataFrame(all_votes)
s.to_excel(writer, sheet_name='Sheet1')
writer.save()

return await send_from_directory('./static/xlsfiles/', file_name=filename)`

The result of this is almost ok, it gives a file named 'overview'. This is also the url of the page.
It should be 'description-title.xlsx', that is also the value of filename when i print it....

Trying

return await send_from_directory('./static/xlsfiles/', file_name=filename, attachment_filename=filename)
Gives an error that attachment_filename is unexpected....

Long story short:

  • is there a way to get it working using the bytesIO solution?
  • if not, how can i set the attachment name ?

Your help would be greatly appreciated again...

kind regards

How to get subprotocols from Websocket Request before accepting it ?

In this exemple :

@app.websocket('/ws')
async def ws():
    await websocket.accept(subprotocol="xxx")
    while True:
        data = await websocket.receive()
        await websocket.send('hello')

When accepting websocket request, we must know the list of sub-protocols queried by the client in the header Sec-WebSocket-Protocol: xxx, yyy
Your code store this header in subprotocols variable, but not provided...
How get this list ?

PUSH example not working

$ QUART_APP=http2_push quart run
Running on https://127.0.0.1:5000 (CTRL + C to quit)
/tmp/quart-original/quart/asgi.py:76: RuntimeWarning: coroutine 'ASGIHTTPConnection._send_push_promise' was never awaited
  self._send_push_promise(send, path)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
[2019-02-07 16:32:43,650] 127.0.0.1:60478 GET /push 2 200 4878 14579

Python 3.6.0 is not compatible

Hi.

You're importing typing.AsyncGenerator here, and the docs claim python 3.6 compatibility, but AsyncGenerator doesn't seem to be included in Python 3.6.0.

I failed to find the changelogs, but I tested with Python images available in Dockerhub, and AsyncGenerator doesn't appear until 3.6.1.

I wonder if this is worth pointing out somewhere in the docs.

This is a relevant issue from the python/typing project.

Keep it up!

Why can't access global app outside context?

I want to create an asycio task in Blueprint, and add_done_callback for it, which is used to delay the task execution in another event loop without hanging the current work. But I can't get current_app in callbacks.

Is it designed for not run task like this on purpose?
Here is my code.

@app.route('/someurl, methods=['POST'])
@admin_required(const.Role_Admin)
def create_something_in_db():
    # do something 
    task = asyncio.ensure_future(current_app.some_obj.really_time_consuming_task(args))
    task.add_done_callback(functools.partial(current_app.db_operator.save_result, arg))

It always crash on current_app.db_operator.save_result execution.

HTTP/2 DoS Vulnerability

Hi,

I would like to report a vulnerability in quart HTTP Server when serving HTTP/2 clients.

In section 10.5 of the HTTP/2 RFC an attack is described where an attacker is sending large SETTINGS frames that includes many settings inside it.
We tested this scenario by opening many connections to the quart server and sending a SETTINGS frame with payload size of 14400 bytes and we were able to cause quart to consume all the machines memory and overload one CPU core with 100% usage by attacking from a single machine.

It is also important to note that quart never closes the connection so the attacker can keep sending those malformed SETTINGS frames, and when under the attack described above, quart responds after a long period to new legitimate requests:

image

image

You can find the script that we used for attacking it and the script that was used to start the server instance in the following link: https://galgoldshtein.co.il/HTTP2/62c31461558c9be64089145736d0d5bf/HTTP2%20Settings%20Frame%20DoS.zip

Thanks.

How to integrate quart with queue system?

So i running Quart with gunicorn, but i facing this problem:

benoitc/gunicorn#1700

I thinking that workers will not solve my problem described above that sometimes the tasks freezing leaving without any response. So i think maybe if i start using Redis to manage this tasks will be more useful since i have scalability in mind. Is there any alternative to gunicorn? I configurating my app wrong?

I have 2 cpus cores:

gunicorn --worker-class quart.worker.GunicornWorker -w 2 server:app -b 0.0.0.0:8080 -t 600

flask_patch : RuntimeError: dictionary changed size during iteration

Hi,

I'm using quart in our application and it works successfully. But if i run the quart application on docker , it returns the following error. I could not find anything about the error. How can i fix this error ?

seffaflik_1  | Traceback (most recent call last):
seffaflik_1  |   File "run.py", line 2, in <module>
seffaflik_1  |     from app import create_app
seffaflik_1  |   File "/code/app/__init__.py", line 2, in <module>
seffaflik_1  |     from .app import create_app
seffaflik_1  |   File "/code/app/app.py", line 7, in <module>
seffaflik_1  |     from quart import Quart,flask_patch
seffaflik_1  |   File "/usr/local/lib/python3.6/site-packages/quart/flask_patch/__init__.py", line 5, in <module>
seffaflik_1  |     patch_all()
seffaflik_1  |   File "/usr/local/lib/python3.6/site-packages/quart/flask_patch/_patch.py", line 83, in patch_all
seffaflik_1  |     _patch_modules()
seffaflik_1  |   File "/usr/local/lib/python3.6/site-packages/quart/flask_patch/_patch.py", line 64, in _patch_modules
seffaflik_1  |     for name, module in sys.modules.items():
seffaflik_1  | RuntimeError: dictionary changed size during iteration
seffaflik_seffaflik_1 exited with code 1

and code blocks :

from quart import Quart,flask_patch
from quart import (
    Blueprint,
    session,
    request,
    render_template,
    jsonify
)

def create_app(config=None, app_name=None, blueprints=None):

    if app_name is None:
        app_name = Config.Config.PROJECT

    if blueprints is None:
        blueprints = DEFAULT_BLUEPRINTS

    app = Quart(app_name)
    configure_app(app, config)
    configure_hook(app)
    configure_logging(app)
    configure_blueprints(app, blueprints)
    configure_extensions(app)
    configure_error_handlers(app)
    configure_filters(app)
    return app

Is there a compatible performance profiler for Quart

I see that there are profiler packages that can give performance metrics on views as they are used during the runtime of the app. I wanted to use such a tool to identify bottlenecks in the views. Is there something that works with Quart apps?

Catch-All URL

I am trying to create catch-all-url route similar to flask, but the route is not working in quart.

Flask:

from flask import Flask, request
app = Flask(__name__)

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):
return 'Hello World'

Quart:

from quart import Quart, request
app = Quart(__name__)

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
async def index(path):
return 'Hello World'

What is the best way to create catch all route in quart?

wrappers/request.py::_load_form_data broken for multipart/form-data

At line https://github.com/pgjones/quart/blob/master/quart/wrappers/request.py#L223

there is no way cgi.FieldStorage could possibly correctly parse multipart/form-data files upload without setting the limit to the content-length so the code should be

content_length = self.headers['content-length']
field_storage = FieldStorage(
                io.BytesIO(raw_data), headers=self.headers, 
                environ={'REQUEST_METHOD': 'POST'}, limit=content_length
)

also at
https://github.com/pgjones/quart/blob/master/quart/wrappers/request.py#L240

sometimes the key is None and this code blows up because multidict only accepts str as key not None

so code should be

elif key:
      self._form.add(key, field_storage_key.value)

With these two changes I get my unit test to pass which I have shown below

from http import HTTPStatus
from copy import deepcopy
from datetime import datetime
from io import BytesIO
from PIL import Image
from werkzeug.test import encode_multipart
from werkzeug.datastructures import FileMultiDict

import pytest
from models import Documents


def create_test_image(name):
    buffered = BytesIO()
    image = Image.new('RGBA', size=(50, 50), color=(155, 0, 0))
    image.save(buffered, 'png')
    file = BytesIO(buffered.getvalue())
    file.name = name
    file.seek(0)
    return file


image_file = create_test_image('filename.png')
fmd = FileMultiDict()
fmd.add_file('file', image_file, filename='filename.png', content_type='image/png')

boundary = 'Test'

_, data = encode_multipart(fmd, boundary=boundary)

headers = {
    'Link': 'https://www.notawebhook.com',
    'Eai-Callback-Token': 'notAtoken',
    'Content-Type': 'multipart/form-data; boundary={}'.format(boundary),
    'Content-Length': len(data)
}

auth = 'Bearer {}'

@pytest.mark.asyncio
async def test_token_works(client, db, token):
    auth_headers = deepcopy(headers)
    auth_headers['Authorization'] = auth.format(token)
    # print('data: {}'.format(data))
    response = await client.post('/v0.0.1/files',
                                 data=data, headers=auth_headers)
    body = await response.json
    print(body)
    assert response.status_code == HTTPStatus.CREATED
    task_id = body['taskId']
    docs = Documents.query.filter_by(task_id=task_id).all()
    assert len(docs) == 1
    doc = docs[0]
    assert doc.page == 1
    assert doc.task_id == task_id
    assert type(doc.time_stamp) is datetime
    image_file.seek(0)
    assert doc.data == image_file.read()

make quart a PEP 561 compatible package

It is great to see a typed package, it sadly is still a rarity. Trying quart out for the first time and having mypy running in my vim and via a Makefile, I was surprised about it not wanting to use the quart's typing information.

According to the mypy documentation it only does that when there is a py.typed file in the installed package. And sure enough, after creating that file (with touch "$VIRTUAL_ENV/lib/python3.7/site-packages/quart/py.typed") it works like a charm.

I don't really know if there is another way to achieve this, but I think adding this file to the distribution would be the easiest way to just make it work out of the box.

ProxyFix?? O.o

Hello.
I use Flask a lot, and Quart looks like good alternative, but I came across a little problem.
With Flask I used to do this:

`
from flask import Flask
from werkzeug.contrib.fixers import ProxyFix

app = Flask(name)
app.wsgi_app = ProxyFix(app.wsgi_app)
`

This was easy way to get "real" client address behind proxy. But i can't find a way to do something similar in Quart. Is there / Will there be any solution? Thnaks...

http2 ssl file upload, suddenly 404 error issue

if __name__ == "__main__":
    ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    ssl_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_COMPRESSION
    ssl_context.set_ciphers('ECDHE+AESGCM')
    ssl_context.load_cert_chain(certfile='xxx.crt', keyfile='xxx.key')
    ssl_context.set_alpn_protocols(['h2', 'http/1.1'])
    app.run(host='0.0.0.0', port=443, ssl=ssl_context)

when i use the http2 and ssl my server is very slow and many 404 err response.
and.. when i upload img files i can only upload small than 20kb..
why this issue bring me?

maybe i think
await request.files <- this line is blocking all request.

my upload source

@app.route('/api/Cms/Shop/Content/Img', methods=['POST'], subdomain="cms")
async def CmsShopContentImg():
    if 'UserGrade' in session:
        Data = await request.files
        if 'file' not in Data:
            return '', 400
        elif Data['file'].filename == '':
            return '', 400
        elif Data['file']:
            filename = sha256(str(datetime.now()).encode('utf-8')).hexdigest() + '.png'
            Data['file'].save(os.path.join(app.config['EDITOR_UPLOAD_FOLDER'], filename))
            returnUrl = { 'url': 'https://xxx.com/shop/content/' + filename}
            return dumps(returnUrl)
    else:
        return '', 401

[Promo] Official Quart logo

Hi, @pgjones

I want to start this disqus because it's important to promotion and visual identity. Good Python framework need good visual stuff! So, I have some ideas about official Quart logo and give you them for free :) Look please.

Handwritten logo

screen shot 2017-12-04 at 12 15 07

Font: Amarillo (this's a paid font, but I already bought it)
Color: RGB 214, 11, 82 (HEX #d60b52)

Literal with text

screen shot 2017-12-04 at 12 43 03

Font: Lifehack Basic (this's a paid font, but I already bought it) + Open Sans (or similar)
Color: RGB 45, 46, 131 (HEX #2d2e83) + similar dark color, like #333333

question regarding websockets

currently I am running a flask web server on the same raspi3 where I also read a lot of sensors (IOT) which are send to the web page. Now I want to split data collection and Webserver to run on two or more Raspis. The data collection Raspis should send data via websocket to the webserver and receive input from the webserver initiated on the webpage. Will quart be able to handle these additonal websockets within the webserver app and how would this be coded? I apprecaite very much your support and suggestions in this matter.

How to get user_agent from quart request

Hi, currently I'm migrating a small service from flask to quart and Im facing an issue related to request
from quart import request
It seems like request from quart doesn't have request.user_agent.platform nor request.user_agent.browser, however request from flask have them.

Are there any plan to add this? or there is any workaround ?

asgi scope type is unknown

Hi, I started getting the following stack trace in the latest quart version:

[2018-11-12 09:33:04,391] ASGI Framework Lifespan error, continuing without Lifespan support
Traceback (most recent call last):
File "/home/nurettin/.local/share/virtualenvs/pylongrun-fEmL5R2s/lib/python3.6/site-packages/hypercorn/asyncio/lifespan.py", line 24, in handle_lifespan
asgi_instance = self.app(scope)
File "/home/nurettin/.local/share/virtualenvs/pylongrun-fEmL5R2s/lib/python3.6/site-packages/quart/app.py", line 1689, in call
raise RuntimeError('ASGI Scope type is unknown')
RuntimeError: ASGI Scope type is unknown
12-Nov-18 09:33:04: quart.serving ERROR: ASGI Framework Lifespan error, continuing without Lifespan support
Traceback (most recent call last):
File "/home/nurettin/.local/share/virtualenvs/pylongrun-fEmL5R2s/lib/python3.6/site-packages/hypercorn/asyncio/lifespan.py", line 24, in handle_lifespan
asgi_instance = self.app(scope)
File "/home/nurettin/.local/share/virtualenvs/pylongrun-fEmL5R2s/lib/python3.6/site-packages/quart/app.py", line 1689, in call
raise RuntimeError('ASGI Scope type is unknown')
RuntimeError: ASGI Scope type is unknown

When multiprocessing using forkserver - DeprecationWarnings appear

These warning messages appear when starting a mp in forkserver.

I'm using python3.7 on a RaspBerryPi 3B running Debian Stretch.

/home/pi/.local/lib/python3.7/site-packages/jinja2/utils.py:485: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
from collections import MutableMapping
/home/pi/.local/lib/python3.7/site-packages/markupsafe/init.py:13: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
from collections import Mapping
/home/pi/.local/lib/python3.7/site-packages/jinja2/utils.py:485: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
from collections import MutableMapping
/home/pi/.local/lib/python3.7/site-packages/markupsafe/init.py:13: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
from collections import Mapping
/home/pi/.local/lib/python3.7/site-packages/jinja2/utils.py:485: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
from collections import MutableMapping
/home/pi/.local/lib/python3.7/site-packages/markupsafe/init.py:13: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
from collections import Mapping
/home/pi/.local/lib/python3.7/site-packages/hyperframe/flags.py:14: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
class Flags(collections.MutableSet):
/home/pi/.local/lib/python3.7/site-packages/hyperframe/flags.py:14: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
class Flags(collections.MutableSet):
/home/pi/.local/lib/python3.7/site-packages/hyperframe/flags.py:14: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working

Exception when processing ACCEPT headers

I built a Quart web server to serve some dynamic KML content. GoogleEarth supports two formats; KML and KMZ. I want to support returning a response in either of the supported formats.

My code looks something like this:

kml_mimetype = 'application/vnd.google-earth.kml+xml'
kmz_mimetype = 'application/vnd.google-earth.kmz'
SUPPORTED_MIMETYPES = (kmz_mimetype, kml_mimetype)

@app.route('kml_update', method=['GET'])
async def handle_kml_update():
    ''' Handle a request to the /kml_update route. '''
    try:
        mimetype = request.accept_mimetypes.best_match(
                SUPPORTED_MIMETYPES, default=kml_mimetype)
    except Exception:
        logger.exception('Error generating KML')

When GoogleEarth attempts to fetch data from the Quart web server's /kml_update route (which it is instructed to do via a KML file containing a NetworkLink tag) I observe an error in my handler function which is generated from Quart when it is processing the Accept headers.

Error generating KML
Traceback (most recent call last):
  File "server.py", line 174, in handle_kml_update
    mimetype = request.accept_mimetypes.best_match(
  File "/Users/claws/.venvs/myenv/lib/python3.6/site-packages/quart/local.py", line 108, in __getattr__
    return getattr(self._get_current_object(), name)
  File "/Users/claws/.venvs/myenv/lib/python3.6/site-packages/quart/wrappers.py", line 291, in accept_mimetypes
    return MIMEAccept(self.headers.get('Accept', ''))
  File "/Users/claws/.venvs/myenv/lib/python3.6/site-packages/quart/datastructures.py", line 144, in __init__
    quality = float(raw_quality.split('=', 1)[-1])
ValueError: could not convert string to float: 'context.kml'

The ACCEPT headers in the request that triggered the error were:

'Accept': 'application/vnd.google-earth.kml+xml;googleearth=context.kml,application/vnd.google-earth.kmz;googleearth=context.kmz'

The main culprit seems to be the ;googleearth=context.kml inapplication/vnd.google-earth.kml+xml;googleearth=context.kml and the googleearth=context.kmz in application/vnd.google-earth.kmz;googleearth=context.kmz.

Quart is only expecting a string of the form q=0.9 in scenarios where a ; is found in an ACCEPT item.

I am not familiar with http ACCEPT specification. Perhaps Quart is correct in its processing of the accept headers against the specification and GoogleEarth is supplying malformed ACCEPT items. If this is the case then this issue can be closed. If not, then it would be nice if the Accept headers got returned without triggering an exception.

Invalid Relative Import in JSON Parsing

The function on_json_loading_failed contains the line: from .exceptions import BadRequest here. This needs to be changed to from ..exceptions import BadRequest or from quart.exceptions import BadRequest.

I'll make a PR.

"application protocol failed to receive SSL data" during upload

cd examples/http2_push
#edit / route to accept POST
#@app.route('/', methods=['POST'])
QUART_APP=http2_push quart run

Now create a payload file:

dd if=/dev/urandom of=payload count=10000

Do POST to /:

curl -d @payload -vsk https://127.0.0.1:5000/

Server console shows this error and then connection hangs:

application protocol failed to receive SSL data
protocol: <asyncio.sslproto.SSLProtocol object at 0x7f1358bdeac8>
transport: <_SelectorSocketTransport fd=8 read=polling write=<idle, bufsize=0>>
Traceback (most recent call last):
  File "lib/python3.7/asyncio/sslproto.py", line 541, in data_received
    self._app_protocol.data_received(chunk)
  File "xyz/hypercorn/hypercorn/asyncio/run.py", line 59, in data_received
    self._server.data_received(data)
  File "xyz/hypercorn/hypercorn/asyncio/h2.py", line 100, in data_received
    self.handle_events(events)
  File "xyz/hypercorn/hypercorn/asyncio/h2.py", line 126, in handle_events
    self.streams[event.stream_id].append(event.data)
KeyError: 1

Support for extensions?

On of the things that makes flask really powerful is the availability of extensions. Do you plan on supporting any? Or maybe have a guide for port existing flask ones to quart?

Adding a way to run a startup / cleanup routine

Hi!

I've been trying to use aiomysql with Quart. Opening a new connection for each request works fine, but isn't quite resource efficient. So I've decided to use a pool.

To create / destroy the pool correctly, I need access to the loop. I can use the signal before_first_request to create the pool. However, I can't seem to find a way of running a method before the loop is closed.

So, I sub-classed the custom worker:

class CustomWorker(GunicornUVLoopWorker):

    def run(self) -> None:
        create_server = asyncio.ensure_future(self._run(), loop=self.loop)

        try:
            self.loop.run_until_complete(create_server)
            self.loop.run_until_complete(self._check_alive())
        finally:
            self.loop.run_until_complete(self.loop.shutdown_asyncgens())
            self.loop.run_until_complete(self._cleanup())
            self.loop.close()

    async def _cleanup(self):
        if not hasattr(app, 'pool'):
            return

        pool.close()
        await pool.wait_closed()
        del app.pool

I was wondering if there was a cleaner way to do this. Especially because now, I can't run the built in server, and have to add a special configuration to pytest to make it run:

@pytest.yield_fixture(autouse=True)
async def run_around_tests():
    # Before each test
    yield
    # After each test

Thanks!

ImportError: cannot import name 'AsyncGenerator'

Install

$ python -m venv venv
$ source venv/bin/activate
$ pip install quart

Edit app file

from quart import Quart

app = Quart(__name__)

@app.route('/')
async def hello():
    return 'hello'

if __name__ == '__main__':
  app.run()

Run
$ python app.py

Error
ImportError: cannot import name 'AsyncGenerator'

Python and PIP version

$ python -V
Python 3.6.0
$ pip -V
pip 10.0.1

websocket.receive() binary data

Hi, I'm successfully using Quart's websocket, and I'm now wondering why websocket.receive() returns str is there a way to get bytes instead? I'm working with a binary protocol, so it would be nice to have raw data access and it sounds weird to encode the input.

Error handlers do not seem to work.

I tried both handlers:


@app.errorhandler(404) 
def page_not_found(e): 
    return render_template('/error_handlers/404.html'), 404

and


def not_found():
    return render_template('/error_handlers/404.html'), 404

app.register_error_handler(404, not_found)

None of these seem to work on Quart. I tried the same code on Flask, which seems to work. You can test this simple code here:

from quart import Quart

app = Quart(__name__)

@app.errorhandler(404)
def page_not_found(e):
    return 'Not found lalala', 404

if __name__ == '__main__':
    app.run()
from flask import Flask

app = Flask(__name__)

@app.errorhandler(404)
def page_not_found(e):
    return 'Not found lalala', 404

if __name__ == '__main__':
    app.run()

$> python test.py

What am I doing wrong?

Thanks.

Automatic reloading in debug mode

As documented here flask provides automatic reloading on code change when the debug mode is enabled.
This doesn't seem to be the case for quart (I tried the QUART_DEBUG (cf here) environment variable, as well as manually setting the app config).
It is a really helpful feature during development and it would be great if quart could offer it too.

with app.app_context() in thread: AttributeError: __enter__

Hi, Im using current_app._get_current_object() to pass the app object into a thread and execute app.app_context() however im facing a run time error regarding: AttributeError: __enter__, after some more investigation adding import quart.flask_patch to the top of my main module didn't work for me nor defining my own Thread class with current_app object attached to it.

class FlaskThread(Thread):
  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.app = current_app._get_current_object()

  def run(self):
    with self.app.app_context():
        super().run()

^ this didn't work for me

My code looks like this:

from threading import Thread
from quart import current_app
from flask_mail import Message
from app import mail

def send_async_email(app, msg):
  with app.app_context():
    mail.send(msg)

def send_email(subject, sender, recipients, text_body, html_body, attachments=None, sync=False):
  msg = Message(subject, sender=sender, recipients=recipients)
  msg.body = text_body
  msg.html = html_body
  if attachments:
    for attachment in attachments:
      msg.attach(*attachment)
  if sync:
    mail.send(msg)
  else:
    Thread(
      target=send_async_email,
      args=(current_app._get_current_object(), msg),
    ).start()

The issue, as I understand, is happening once the execution reached with app.app_context(): after that line, the enter method for app will be called but it seems like that method is not implemented in from quart import current_app

Stacktrace:

Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/Users/leninarias/go/src/app.theia/account-recovery/venv/lib/python3.7/site-packages/sentry_sdk/integrations/threading.py", line 47, in run
    reraise(*_capture_exception())
  File "/Users/leninarias/go/src/app.theia/account-recovery/venv/lib/python3.7/site-packages/sentry_sdk/_compat.py", line 52, in reraise
    raise value
  File "/Users/leninarias/go/src/app.theia/account-recovery/venv/lib/python3.7/site-packages/sentry_sdk/integrations/threading.py", line 45, in run
    return old_run(*a, **kw)
  File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/leninarias/go/src/app.theia/account-recovery/app/email.py", line 7, in send_async_email
    with app.app_context():
AttributeError: __enter__

I'll continue investigating the issue but I feel like this is an internal issue with Quart (if isn't pardon me, Im still a newbie on python)

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.