pallets / quart

An async Python micro framework for building web applications.
https://quart.palletsprojects.com
MIT License
2.91k stars 159 forks source link

http2 ssl file upload, suddenly 404 error issue #30

Closed XploitKR closed 5 years ago

XploitKR commented 6 years ago
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
pgjones commented 6 years ago

I think the 404 must be an issue with the request you are making (to a path that you don't have defined), rather than anything to do with HTTP/2 or SSL.

How is the file being sent? If it is not streamed then it would likely take time. I'm not sure what the 20kb issue is, is there an error? Is there a restriction on the system?

XploitKR commented 6 years ago

when i use no ssl, http2 server and my webapp working perfectly.

img upload more than 20kb work fine.

i tried normal html form, dropzone.js, ngx-editor image upload.

all the same issue.

pgjones commented 6 years ago

Does it work with SSL but no HTTP/2?

It is quite hard to figure this out from the information given, are there any error messages or warnings?

XploitKR commented 6 years ago

no error, no warnings.. i think await request.files infinity await.

only image upload things.

suddenly 404 error come out static img, js, css etc.

sorry for my bad eng.T.T

XploitKR commented 6 years ago
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
UPLOAD_FOLDER = os.path.join(APP_ROOT, 'static/shop/imgs')
EDITOR_UPLOAD_FOLDER = os.path.join(APP_ROOT, 'static/shop/content')
NOTICE_UPLOAD_FOLDER = os.path.join(APP_ROOT, 'static/notice/imgs')
MAGAZINE_UPLOAD_FOLDER = os.path.join(APP_ROOT, 'static/magazine/imgs')
MAGAZINE_CONTENT_UPLOAD_FOLDER = os.path.join(APP_ROOT, 'static/magazine/content')

app = Quart(__name__, static_url_path='', static_folder='static')
app.config['SERVER_NAME'] = "xxxx.com"
app.url_map.host_matching = True
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['EDITOR_UPLOAD_FOLDER'] = EDITOR_UPLOAD_FOLDER
app.config['NOTICE_UPLOAD_FOLDER'] = NOTICE_UPLOAD_FOLDER
app.config['MAGAZINE_UPLOAD_FOLDER'] = MAGAZINE_UPLOAD_FOLDER
app.config['MAGAZINE_CONTENT_UPLOAD_FOLDER'] = MAGAZINE_CONTENT_UPLOAD_FOLDER
cors(app)

@app.route('/', methods=['GET'], subdomain="cms")
async def rootCms():
    #return await render_template('index.html', session = session)
    return await app.send_static_file('cms/index.html')

@app.route('/<path:path>', methods=['GET'], subdomain="cms")
async def staticfileCms(path):
    #return await render_template('index.html', session = session)
    if path.find('shop') == 0 or path.find('notice') == 0 or path.find('magazine') == 0:

        return await app.send_static_file(path)
    else:
        return await app.send_static_file('cms/'+path)

@app.route('/', methods=['GET'], subdomain="m")
async def rootMobile():
    #return await render_template('index.html', session = session)
    return await app.send_static_file('mobile/index.html')

@app.route('/<path:path>', methods=['GET'], subdomain="m")
async def staticfileMobile(path):
    #return await render_template('index.html', session = session)
    if path.find('shop') == 0 or path.find('notice') == 0 or path.find('magazine') == 0:

        return await app.send_static_file(path)
    else:
        return await app.send_static_file('mobile/'+path)

@app.route('/', methods=['GET'])
async def root():
    #return await render_template('index.html', session = session)
    return await app.send_static_file('index.html')

@app.route('/<path:path>', methods=['GET'])
async def staticfile(path):
    #return await render_template('index.html', session = session)
    return await app.send_static_file(path)

from Routes.User import *
from Routes.Cms import *
from Routes.Shop import *
from Routes.Notice import *
from Routes.Magazine import *

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='semoplace.crt', keyfile='semoplace.key')
    ssl_context.set_alpn_protocols(['h2', 'http/1.1'])
    app.run(host='0.0.0.0', port=443, ssl=ssl_context)
    #app.run(host='0.0.0.0', port=80)

my main.py source code.

pgjones commented 6 years ago

Thanks, I'm not sure from this what the issue is. I'll keep it in mind and try thinking what it could be.

If you make any progress please update.

XploitKR commented 6 years ago

ok. im tested migrate to flask.

when using flask working perfectly with same code.

pgjones commented 5 years ago

@kowbot I think this is likely fixed in the latest version of Hypercorn - as I suspect it was a flow control issue fixed in this commit. Could you try with the latest code and see if this is still a problem?

pgjones commented 5 years ago

Also note #41 which I think also impacts this.