Декодирование и десериализация URL не удаются - PullRequest
0 голосов
/ 15 июня 2019

Использование буфера протокола Я сериализирую данные и передаю их, добавляя их в качестве параметра в запросы HTTP GET, отправляемые во Flask. Десериализация данных иногда дает сбой в зависимости от содержимого параметров (например, если параметр url содержит «% F0»).

Я пытался использовать разные кодировки для кодирования / декодирования, а также пытался добавить правильный заголовок к типу содержимого параметра запроса в application / x-protobuf. * ​​1003 *

Это код фляги, обрабатывающей входящий GET-запрос.

def _ai_request_stub(min_params: List[str], on_parameter_available: Callable[[], Response]) -> Response:
    """
    This stub is designed for GET requests.
    """
    from flask import request
    missing_params = list(filter(lambda p: p not in request.args, min_params))
    if missing_params:
        return Response(response="The request misses one of the parameters [\"" + "\", ".join(missing_params) + "\"]",
                        status=400, mimetype="text/plain")
    else:
        return on_parameter_available()


@app.route("/ai/control", methods=["GET"])
def control():
    def do() -> Response:
        from aiExchangeMessages_pb2 import Control
        from flask import request
        control_msg = Control()
        control_msg.ParseFromString(request.args["control"].encode())
        return Response(response="Fine", status=200, mimetype="application/x-protobuf")

    return _ai_request_stub(["control"], do)

Это код, создающий и отправляющий запрос GET.

class AIExchangeService:
    from aiExchangeMessages_pb2 import SimStateResponse, DataRequest, DataResponse, Control, Void, AiID
    from typing import Dict, AnyStr, Any

    def __init__(self, host: str, port: int):
        self.host = host
        self.port = port

    [...]

    def _do_get_request(self, address: str, params: Dict[str, AnyStr]) -> HTTPResponse:
        """
        :return: The response object of the request
        """
        from urllib.parse import urlencode
        from http.client import HTTPConnection
        connection = HTTPConnection(host=self.host, port=self.port)
        print(params)
        connection.request("GET", address + "?" + urlencode(params),
                           headers={"content-type": "application/x-protobuf; charset=utf-8"})
        return connection.getresponse()

    def control(self, commands: Control) -> Void:
        response = self._do_get_request("/ai/control", {"control": commands.SerializeToString()})
        if response.status == 200:
            print("Controlled")
        else:
            print(response.status)
            print(response.reason)

    [...]

Это код протобуфера, показывающий структуру объекта Control.

message AiID {
    [...]
}

message Control {
    message AvCommand {
        double accelerate = 1;
        double steer = 2;
        double brake = 3;
    }

    enum SimCommand {
        RESUME = 0;
        FAIL = 1;
        CANCEL = 2;
    }
    AiID aid = 1;
    oneof command {
        AvCommand avCommand = 2;
        SimCommand simCommand = 3;
    }
}

Вызов commands.SerializeToString() во втором фрагменте метода control(...) дает b'\n\x13\n\n\n\x08fancySid\x12\x05\n\x03ego\x12\t\t\x00\x00\x00\x00\x00\x00\xf0?'. Оценка address + "?" + urlencode(params) во втором фрагменте в методе _do_get_request(...) дает вывод /ai/control?control=%0A%13%0A%0A%0A%08fancySid%12%05%0A%03ego%12%09%09%00%00%00%00%00%00%F0%3F, который, по-видимому, такой же, но в кодировке urlencoded.

При отправке этого запроса GET на флешку request.args["control"] в первом фрагменте метода control() выдается '\n\x13\n\n\n\x08fancySid\x12\x05\n\x03ego\x12\t\t\x00\x00\x00\x00\x00\x00�?', который больше не является той же сериализованной строкой. Попытка десериализации этой строки не удалась с ошибкой google.protobuf.message.DecodeError: Error parsing message.

Что можно сделать, чтобы колба правильно прочитала параметр?

1 Ответ

0 голосов
/ 18 июня 2019

Запрос GET не сделан для отправки огромных необработанных двоичных данных.Вместо этого должен использоваться запрос POST.И действительно, почтовый запрос работает просто отлично.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...