How to decode protobuf obtained via axios using typescript

482 Views Asked by At

I'm new to typescript, and I'm trying to understand how to use axios to download real-time gtfs data (which is in protobuf form). I'm getting an illegal buffer error when I try to run this code. I've posted the error in full below.

import axios from "axios";
import * as GtfsRealtimeBindings from "gtfs-realtime-bindings";

const url = "https://www.rtd-denver.com/files/gtfs-rt/TripUpdate.pb";
export type RealtimeGtfsUrl = string;

export async function decodeRealtimeGtfs(
  url: RealtimeGtfsUrl,
): Promise<GtfsRealtimeBindings.transit_realtime.FeedMessage> {
  return await axios.get(url).then((response) => {
    return GtfsRealtimeBindings.transit_realtime.FeedMessage.decode(
      response.data,
    );
  });
}

const result = decodeRealtimeGtfs(url);

/Users/.../playground/node_modules/protobufjs/src/reader.js:47 throw Error("illegal buffer"); ^

Error: illegal buffer at create_typed_array (/Users/.../playground/node_modules/protobufjs/src/reader.js:47:15) at create_buffer (/Users/.../playground/node_modules/protobufjs/src/reader.js:63:23) at Function.create_buffer_setup (/Users/.../playground/node_modules/protobufjs/src/reader.js:64:15) at Function.decode (/Users/.../playground/node_modules/gtfs-realtime-bindings/gtfs-realtime.js:134:34) at /Users/.../playground/test.cjs:48:82 at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

1

There are 1 best solutions below

0
Phil On

The response is in a binary format where Axios defaults to expecting JSON / plain text.

The decoder expects an ArrayBuffer so all you should need to do is tell Axios what response type to expect.

Also, don't mix await with .then(); it just makes for confusing code.

export async function decodeRealtimeGtfs(
  url: RealtimeGtfsUrl,
): Promise<GtfsRealtimeBindings.transit_realtime.FeedMessage> {
  const { data } = await axios.get(url, { responseType: "arraybuffer" });
  return GtfsRealtimeBindings.transit_realtime.FeedMessage.decode(data);
}