Сериализация ProtoBuf через IHttpHandler дает неверные результаты - PullRequest
0 голосов
/ 07 февраля 2019

Я использую ASP.NET WebForms, что означает, что я буду отправлять данные Protobuf через страницы ASPX или ASHX.

Я пытаюсь создать файл GTFSRT, для которого существует пакет Nuget с именем GTFSRealTimeBindings.При этом используются Protobuf и Protobuf-net для сжатия и отправки данных.

Проблема, с которой я сталкиваюсь, заключается в том, что при отправке данных что-то перемешивается, поэтому их нельзя прочитать на принимающей стороне.и я не уверен, как это исправить.Я думаю, что это в кодировке, но я не устанавливаю это, поэтому я не уверен, как это изменить.

Я закончил тем, что написал http-обработчик (страница Ashx), который загрузит GTFSфайл из другого источника, а затем просто попробуйте переслать его.Я знаю, что файл GTFS можно прочитать и расшифровать из другого источника.Но каждый раз, когда я пытаюсь сервировать файл со своей страницы Ashx, я не могу декодировать объект protbuf. * ​​1007 *

Вот очень простой набор кодов:

public class Vehicles : IHttpHandler
{

  public void ProcessRequest(HttpContext context)
  {

      WebRequest req = HttpWebRequest.Create("https://cdn.mbta.com/realtime/VehiclePositions.pb");
      FeedMessage feed = Serializer.Deserialize<FeedMessage>(req.GetResponse().GetResponseStream());

      Serializer.Serialize(context.Response.OutputStream, feed);
  }
}

В этом фрагменте,вы заметите, что я загружаю файл Protobuf с cdn.mbta.com, затем просто пытаюсь взять полученный результат и передать его обратно.

Когда я пытаюсь прочитать это в моем примере приложения:

WebRequest req = HttpWebRequest.Create("http://localhost:54988/Secure/Admin/Reports/GtfsRt/Vehicles.ashx");
FeedMessage feed = Serializer.Deserialize<FeedMessage>(req.GetResponse().GetResponseStream());

Я получаю следующее сообщение: «Недействительный проводной тип;обычно это означает, что вы перезаписали файл без усечения или установки длины;см. http://stackoverflow.com/q/2152978/23354'

Если я запускаю Fiddler, когда эта страница нажата, я замечаю, что ответ, который я получаю от cdn.mbta.com, отличается от ответа, который дает эта страница (за исключением, конечно, заголовков).

Например, первые две строки на mbta.com в fiddler показывают:

2.0] y1601 "T

Но первые две строки моего ответа: 2,0 Втy1601 "N

Любые идеи о том, что вызывает это, и как я могу это исправить?Я попытался установить кодировку, используя

content.Response.ContentEncoding=Encoding.Utf8

Я и я прошел и попробовал все другие кодировки, чтобы попытаться установить его правильно.

====== ОБНОВЛЕНИЕ ====== В ответ на вопрос Марка я взял строку Base64 полезной нагрузки ответа, и ответ из первого источника не совпадает с ответом после его переадресации.

Ответ от mbta.com(ограничивается первые несколько символов): Cg0KAzIuMBAAGI / e8eIFEl0KBXkwNzIzIlQKHAoIMzkyNTAwNjcqAjg4MAAaCDIwMTkwMjA3IABCDg

1036 * Ответ от моей службы (ограничивается первые несколько символов): CgsKAzIuMBiP3vHiBRJXCgV5MDcyMyJOChgKCDM5MjUwMDY3GggyMDE5MDIwNyoCODgSFA3skilCFQ 1038 * Как вы можете видеть, что они различны.Я буду работать над решением, которое я могу загрузить, чтобы продемонстрировать проблему.Еще раз спасибо!

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Я думаю, что смог найти решение.

Мой веб-код превратился в следующее:

    public void ProcessRequest(HttpContext context)
    {
        context.Response.Clear();
        context.Response.Buffer = true;
        context.Response.AddHeader("content-disposition", "attachment;filename=VehiclePositions.pb");
        context.Response.ContentType = "application/x-protobuf";
        WebRequest req = HttpWebRequest.Create("https://cdn.mbta.com/realtime/VehiclePositions.pb");
        FeedMessage feed = Serializer.Deserialize<FeedMessage>(req.GetResponse().GetResponseStream());
        using (MemoryStream ms = new MemoryStream())
        {
            Serializer.Serialize(ms, feed);
            context.Response.BinaryWrite(ms.ToArray());
            context.Response.End();
        }
    }

Не уверен, было ли это связано или нет, но какОтлаживая, я заметил, что иногда запрос не попадает в веб-сервис.Убрана аутентификация, и теперь она может декодировать сообщение.Я полагаю, что это работало раньше, когда я проходил через веб-код, но об этом нужно знать.Еще раз спасибо, Марк!

0 голосов
/ 07 февраля 2019

Как выглядит ответ в Fiddler, становится сложно, если вы не смотрите на двоичный файл;Вам лучше всего взглянуть на вкладку HexView;все в зеленом - это заголовки;все в черном - это полезная нагрузка.

Используя ваш исходный URL-адрес https://cdn.mbta.com/realtime/VehiclePositions.pb, я отмечаю, что это ~ 26k, но с 66591 байтами полезной нагрузки, с использованием gzip внутри;так что вам нужно убедиться, что вы приняли предложение Fiddler сначала декодировать это - затем я сделал «copy as base-64» в fiddler (только полезную нагрузку, а не заголовки на вкладке HexView) и провел его через https://protogen.marcgravell.com/decode (с использованием опции base-64), и он проанализировал до конца.

Итак: я бы предложил:

  • сделать аналогичный запросваш обработчик
  • проверьте длину - это 66k?или 26к?или что-то другое?и если это 26k, помечается ли оно как gzip-кодированное?
  • , когда вы копируете полезную нагрузку base-64 для каждого (gzip-декодированный, если необходимо): является ли base-64 одинаковым?
  • что https://protogen.marcgravell.com/decode говорит о base-64 от вашего обработчика?принимает ли он его и анализирует до конца?

Это должно помочь вам определить проблему;или помогите мне отождествить это с вами.

...