C # Получить чанк ответа HTTP POST? - PullRequest
1 голос
/ 01 декабря 2019

Я работаю с API, который принимает HTTP-запрос POST вместе с данными запроса в форме URL в качестве полезной нагрузки. Ответ от сервера разбивается на фрагменты, и каждый блок содержит один объект JSON. Я пытаюсь прочитать и проанализировать ответ сервера по чанку из C #, чтобы я мог взять чанк, преобразовать его с помощью Newtonsoft и выполнить любую необходимую обработку на этом этапе. Сервер возвращает неизвестное количество записей на запрос - это может быть 0 записей или тысячи кусков.

Мои исследования и тестирование типичных решений, таких как HttpClient, показывают, что эти библиотеки "обрабатывают" куски, просто объединяя все в один поток ответов. Кроме того, я прочитал другие посты, которые указывают, что если сервер не соответствует спецификации 100%, возможно даже получить исключение в конце потока.

Я рассмотрел следующие решения, но ни один из них не кажется оптимальным:

  1. Считывает поток из HTTP-ответа char-by-char, считая символы { и }, чтобы найти начало и конец объекта JSON,Каждый раз, когда закрытие } найдено, анализируйте объект. Это невероятно некрасиво, неэффективно и не является общим - оно предполагает, что каждый ответ JSON является объектом, и его необходимо изменить, если, например, сервер отправит массив JSON ([ и ]) вместо этого или даже простоодиночные строки JSON на чанк.

  2. Пропустите HttpRequest / HttpClient полностью и делайте все в необработанных сокетах. Затем я могу проанализировать размеры чанка, прочитать ровно столько байтов из потока сокетов и выполнить соответствующий анализ. Это бы сработало, за исключением того, что мне кажется, что нужно «заново изобретать колесо», поскольку мне нужно реализовать кодировку URL для тела POST, разбора заголовка, SSL / TLS и т. Д. Все это в основном «решено» HttpClient, поэтому реализацияЭто само по себе снова кажется плохой идеей, если только по какой-то другой причине я мог бы легко представить ошибку синтаксического анализа.

  3. Поскольку сервер отправляет объект JSON на блок, прочитайте весь ответ,затем найдите }{ и рассмотрите их как точку разделения для объектов JSON (поскольку в реальном JSON между двумя объектами, входящими в список, будет ,). В лучшем случае это кажется ненадежным - предполагается, что по обе стороны от объекта JSON каждого блока нет пробелов. Это также неэффективно, поскольку, если бы сервер возвращал миллионы записей, весь ответ должен был бы храниться в оперативной памяти. Ответ с миллионами записей может составить более 1 ГБ по сотням фрагментов. Хотя это не обязательно проблема для машины с большим количеством оперативной памяти, это неоправданно неэффективный метод анализа данных, пригодных для обработки по своему дизайну.

Идеальный сценарий - это своего рода перечислитель, который читает поток HTTP по чанкам, поскольку API создает чанки, в которых каждый чанк представляет ровно один объект JSON. Это то, что я рассматривал для реализации в варианте 2, но опять-таки, кажется, что нужно много изобретать колесо и возможно появление серьезных ошибок. Второй лучший вариант - это способ получить необработанный базовый поток сокетов от HttpClient после того, как он выполнил запрос и проанализировал заголовки - другими словами, способполучить поток, который включает в себя размеры и разделители чанков, так что тогда я могу проанализировать этот поток напрямую, извлекая размеры чанков и в основном выполняя # 2 выше, но без необходимости писать свой собственныйРеализация HTTP.

Каков наилучший вариант для меня, чтобы реализовать эту функцию?

...