KeyError при отправке POST-запроса с сервера Unity C# на Flask Python - PullRequest
0 голосов
/ 24 апреля 2020

Я переносил приложение веб-сервера с PHP на Python Flask. Я пытаюсь отправить запрос POST с Unity C# на Python Flask сервер. Однако я получаю ошибки. Первоначально код Unity был от использования PHP сервера, который работал нормально.

Оригинальный php серверный код, который работал нормально.

$input = file_get_contents("php://input");
$input_decoded = json_decode($input, true);
if (isset($input_decoded["data"])) {
    processMessage($input_decoded);
}

Я пробовал несколько вещей.

  • Если я заменил ключ в Unity на что-то другое (например, data2), ошибка в Flask по-прежнему говорит о данных Key error.

Код Unity

List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
formData.Add(new MultipartFormDataSection("data=" + query));
UnityWebRequest www = UnityWebRequest.Post("http://example.com:5000/path/", formData);
yield return www.SendWebRequest();

if (www.isNetworkError || www.isHttpError)
{
    Debug.Log(www.error);
}

Код сервера

from flask import Flask, request

app = Flask(__name__)

@app.route('/path/', methods=['POST'])
def show_subpath():
    data = request.form['data']
    return data

Flask ошибка:

123.456.789.012 - - [24/Apr/2020 03:49:54] "POST /path/ HTTP/1.1" 500 -
Traceback (most recent call last):
  File "/opt/anaconda3/lib/python3.7/site-packages/flask/app.py", line 2463, in __call__
    return self.wsgi_app(environ, start_response)
  File "/opt/anaconda3/lib/python3.7/site-packages/flask/app.py", line 2449, in wsgi_app
    response = self.handle_exception(e)
  File "/opt/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1866, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/opt/anaconda3/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/opt/anaconda3/lib/python3.7/site-packages/flask/app.py", line 2446, in wsgi_app
    response = self.full_dispatch_request()
  File "/opt/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1951, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/opt/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1820, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/opt/anaconda3/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/opt/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
    rv = self.dispatch_request()
  File "/opt/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/jupyter/example_flask/byebye.py", line 7, in show_subpath
    data = request.form['data']
  File "/opt/anaconda3/lib/python3.7/site-packages/werkzeug/datastructures.py", line 443, in __getitem__
    raise exceptions.BadRequestKeyError(key)
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'data'
123.456.789.012 - - [24/Apr/2020 03:50:28] "POST /path/ HTTP/1.1" 500 -

Ошибка Unity:

HTTP/1.1 500 Internal Server Error
UnityEngine.Debug:Log(Object)
FrostweepGames.Plugins.GoogleCloud.SpeechRecognition.Examples.<doSpeach>d__9:MoveNext() (at Assets/scripts/player.cs:54)
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

Как это исправить, чтобы я мог отправить свой POST запрос?

Редактировать: я уверен, но думаю, что, возможно, существуют различные типы запросов POST, поэтому это не так легко работает? Как, может быть, составной POST - это не то, что Flask использует?

Редактировать 2: я мог бы использовать python для отправки запроса POST следующим образом, и он отлично работает. (Но код Unity имеет ошибку, как указано выше)

import requests
r = requests.post("http://example.com:5000/path/", data={'data': 'hi'})
print(r.text) # prints "hi"

Редактировать 3: При отладке я обнаружил, что сервер Flask получал пустую строку b'', когда я печатаю request.data (веб-сервер получил запрос с пустым телом), поэтому он не мог найти значение для ключа data.

Редактировать 4: я пытался добавить

www.chunkedTransfer = false;
www.useHttpContinue = false;

к коду Unity прямо перед yield на основе советы на форумах единства но это не сработало. Запрос был по-прежнему пустым.

Редактировать 5: предыдущий рабочий код был подключен к серверу https PHP, а новый код - к серверу http. Переход с https на http, возможно, повлиял на него, основываясь на post 17 на этой странице форумов Unity.

Редактировать 6: Я был не прав. Запрос не пустой.

request.data # is b''
request.form` # is ImmutableMultiDict([(None, 'data=co')])

Я предположил, что request.data печатал все данные в запросе, и поскольку он был пустым, я предположил, что запрос был пустым. Но request.form фактически имел информацию о запросе. В этом случае строка запроса была 'co'.

1 Ответ

0 голосов
/ 24 апреля 2020

Поскольку на сервер отправляется только один параметр, его можно упростить до следующего:

Unity: вместо выполнения data=query мы просто помещаем туда строку запроса.

formData.Add(new MultipartFormDataSection(query));

Flask: ImmutableMultiDict просто становится словарем в форме {None: <content>}.

from flask import Flask, request

app = Flask(__name__)

@app.route('/path/', methods=['POST'])
def show_subpath():
    data = request.form.to_dict()[None]
    return data
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...