Запрос Flask.get_data() не обрабатывает символ UTF-8

#python #flask #curl

#python #flask #curl

Вопрос:

Я написал простой веб-сервис Flask на Python, который ожидает HTTP POST-запросы со строкой в качестве данных.

 @app.route('/hello', methods=['POST'])
def hello():

json_response = {}
data = request.get_data(as_text=True)

json_response['data'] = data
return json_response
  

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

 curl 127.0.0.1:5000/hello -X POST -H "Content-Type: text/plain" -d "hello world"
{
  "data": "hello world"
}
  

Но когда я пытаюсь вызвать его с помощью строки, содержащей символ UTF-8, символ UTF-8 не читается должным образом и вместо этого заменяется символом замены (как decode('utf-8', 'replace') было бы):

 curl 127.0.0.1:5000/hello -X POST -H "Content-Type: text/plain" -d "hello €"
{
  "data": "hello ufffd"
}
  

Я думал, что весь смысл get_data(as_text=True) в том, чтобы прочитать данные в виде строки Unicode? Я что-то здесь упускаю?

Комментарии:

1. Вы уверены, что отправляете это как UTF-8? Кроме того, что, если вы объявите "Content-type: text/plain; charset=UTF-8" в своей команде cURL? Имеет ли это значение?

2. Хм, теперь, когда вы упомянули об этом, нет. Я не уверен. Я использую Windows cmd, если это представляет какой-либо интерес. Я попытался добавить «charset = UTF-8», но, к сожалению, это ничего не изменило.

Ответ №1:

Я не могу воспроизвести это с помощью Flask 1.1.2 на macOS с использованием iTerm:

 from flask import *

app = Flask(__name__)

@app.route('/hello', methods=['POST'])
def hello():
    data = request.get_data(as_text=True)
    return {'data': data}

if __name__ == '__main__':
    app.run(debug=True)
  
 ~ $ curl 127.0.0.1:5000/hello -X POST -H "Content-Type: text/plain" -d "hello world"
{
  "data": "hello world"
}
~ $ curl 127.0.0.1:5000/hello -X POST -H "Content-Type: text/plain" -d "hello world€"
{
  "data": "hello worldu20ac"
}
  

Я склонен полагать, что ваш терминал на самом деле вообще не кодирует это как UTF-8.

Для дальнейшего доказательства (и во избежание проблем с терминалом) мы можем создать полезную нагрузку, которая сертифицирована в формате utf-8, и опубликовать ее:

 ~ $ python3
>>> open("data.txt", "w", encoding="utf-8").write("kräftskiva")
10
~ $ curl 127.0.0.1:5000/hello -X POST -H "Content-Type: text/plain" -d @data.txt
{
  "data": "kru00e4ftskiva"
}
~ $
  

Комментарии:

1. Спасибо! Я использую Windows cmd, и действительно кажется, что на самом деле он не отправлял символ UTF-8 как UTF-8. Выполнение, как вы предлагаете, с использованием файла в кодировке UTF-8 в качестве входных данных вместо этого, сделало свое дело.