Запрос PUT для приложения Flask на сервере Meinheld отклоняет curl --upload_file с ошибкой 417 - PullRequest
0 голосов
/ 31 октября 2019

ОБНОВЛЕНИЕ : Похоже, это связано с ошибкой: https://github.com/mopemope/meinheld/pull/102

Минимальные файлы:

У меня есть следующее веб-приложение Flask:

# hello.py
from flask import Flask, request
app = Flask(__name__)

data = {}


@app.route('/', defaults={'path': ''})
@app.route('/<path:path>', methods=['GET', 'PUT'])
def f(path):
    if request.method == 'PUT':
        app.logger.info(f'---PUT---\npath: {path}')
        data[path] = request.data
        return f"Saved to /{path}\n", 201, {'location': f'/{path}'}
    else:
        app.logger.info(f'---GET---\npath: {path}')
        try:
            return data[path]
        except KeyError:
            return f"Not found (/{path})\n", 404

И следующий test.html файл:

<h1>Test upload</h1>

Работает:

Когда я запускаю его с помощью сервера разработки Flask, он работает:

Серверокно:

$ FLASK_APP=hello.py flask run --port 5001
* Serving Flask app "hello.py"
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5001/ (Press CTRL+C to quit)

Клиент:

$ curl -v localhost:5001/test.html
* About to connect() to localhost port 5001 (#0)
*   Trying ::1...
* Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 5001 (#0)
> GET /test.html HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:5001
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 404 NOT FOUND
< Content-Type: text/html; charset=utf-8
< Content-Length: 23
< Server: Werkzeug/0.16.0 Python/3.7.1
< Date: Thu, 31 Oct 2019 17:15:31 GMT
<
Not found (/test.html)
* Closing connection 0

Сервер:

127.0.0.1 - - [31/Oct/2019 10:15:31] "GET /test.html HTTP/1.1" 404 -

Клиент:

$ curl -v -T test.html localhost:5001
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                Dload  Upload   Total   Spent    Left  Speed
0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* About to connect() to localhost port 5001 (#0)
*   Trying ::1...
* Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 5001 (#0)
> PUT /test.html HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:5001
> Accept: */*
> Content-Length: 20
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
} [data not shown]
* We are completely uploaded and fine
* HTTP 1.0, assume close after body
< HTTP/1.0 201 CREATED
< Location: http://localhost:5001/test.html
< Content-Type: text/html; charset=utf-8
< Content-Length: 20
< Server: Werkzeug/0.16.0 Python/3.7.1
< Date: Thu, 31 Oct 2019 17:15:39 GMT
<
{ [data not shown]
Saved to /test.html
100    40  100    20  100    20   4477   4477 --:--:-- --:--:-- --:--:--  5000
* Closing connection 0

Сервер:

127.0.0.1 - - [31/Oct/2019 10:15:39] "PUT /test.html HTTP/1.1" 201 -

Клиент:

$ curl -v localhost:5001/test.html
* About to connect() to localhost port 5001 (#0)
*   Trying ::1...
* Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 5001 (#0)
> GET /test.html HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:5001
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: text/html; charset=utf-8
< Content-Length: 20
< Server: Werkzeug/0.16.0 Python/3.7.1
< Date: Thu, 31 Oct 2019 17:15:43 GMT
<
<h1>Test upload</h1>
* Closing connection 0

Сервер:

127.0.0.1 - - [31/Oct/2019 10:15:43] "GET /test.html HTTP/1.1" 200 -

Не работает:

Однако, как говорится в документации Flask, сервер Flask не должен бытьиспользуется в производстве. Я обычно использую Gunicorn вместе с рабочими мейнхельдов;но в этом случае meinheld, похоже, не обрабатывает запрос PUT должным образом.

Если добавить файл hello-mh.py:

from meinheld import server

from hello import app

if __name__ == '__main__':
    server.listen(("0.0.0.0", 5001))
    server.run(app)

и запустить сервер:

$ python3 hello-mh.py

Клиент:

$ curl -v localhost:5001/test.html
* About to connect() to localhost port 5001 (#0)
*   Trying ::1...
* Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 5001 (#0)
> GET /test.html HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:5001
> Accept: */*
>
< HTTP/1.1 404 NOT FOUND
< Server: meinheld/1.0.1
< Date: Thu, 31 Oct 2019 17:16:04 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 23
< Connection: close
<
Not found (/test.html)
* Closing connection 0

Сервер:

"127.0.0.1 - - [31/Oct/2019:10:16:04 -0900] "GET /test.html HTTP/1.1" 404 23 "-" "curl/7.29.0"

Клиент:

$ curl -v -T test.html localhost:5001
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                Dload  Upload   Total   Spent    Left  Speed
0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* About to connect() to localhost port 5001 (#0)
*   Trying ::1...
* Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 5001 (#0)
> PUT /test.html HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:5001
> Accept: */*
> Content-Length: 20
> Expect: 100-continue
>
* Done waiting for 100-continue
0    20    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0} [data not shown]
* We are completely uploaded and fine
< HTTP/1.1 417 Expectation Failed
< Content-Type: text/html
< Server: meinheld/1.0.1
* no chunk, no close, no size. Assume close to signal end
<
{ [data not shown]
100   118    0    98  100    20     97     19  0:00:01  0:00:01 --:--:--    97
* Closing connection 0
<html><head><title>Expectation Failed</title></head><body><p>Expectation Failed.</p></body></html>

Сервер:

"127.0.0.1 - - [31/Oct/2019:10:16:08 -0900] "PUT /test.html HTTP/1.1" 417 98 "-" "curl/7.29.0"
...