9

I am attempting to edit an instance of Axios so that the response type should be a 'stream' rather than standard JSON.

It doesn't seem clear to me from other posts on S.O. how this can be accomplished.

Is this a dead-end??

My Current Axios Instance :

import axios from 'axios';
import { URL } from '../urls';
import {
  requestHandler,
  successHandler,
  errorHandler,
} from './Handlers';

const Api = axios.create({
  baseURL: `${URL}`,
  withCredentials: true,
});

Api.interceptors.request.use((request) => requestHandler(request));
Api.interceptors.response.use((response) => successHandler(response), (error) => errorHandler(error));

export default Api;

Implemented :

const query = {"selections":{"TABLE_A":["COLUMN1"]},"filters":[{"predicates":[]}],"joins":[],"sorts":[],"limit":100,"offset":0}
const response = await Api.post('/data', query);

The axios signature for post looks like this :
axios.post(url[, data[, config]])
Example 1
Example 2

This signature doesn't seem to indicate that the newly created instance of axios has a property relating to streams. Ideally, I would be able to do something like this:

const response = await Api.post(URL, responseType: 'stream', query);

or potentially :

const response = await Api(responseType: 'stream').post(URL, query);
Torc
  • 1,148
  • 6
  • 20
  • 43

2 Answers2

11

While it seems possible to specify a responseType of 'stream' like this :

const response = await Api({
    url: '/data',
    method: 'POST',
    responseType: 'stream',
    data: query
}); 

Axios' xhr.js file will throw this warning in the browser :

The provided value 'stream' is not a valid enum value of type XMLHttpRequestResponseType.

Digging a bit further into the documentation :
Axios Request Configuration indicates that 'stream' is an acceptable responseType. Specifically, if you take a look within axios/index.d.ts :

export type ResponseType = 
  | 'arraybuffer' 
  | 'blob' 
  | 'document' 
  | 'json' 
  | 'text' 
  | 'stream' 

However, the WHATWG spec for an XMLHttpRequest shows that 'stream' isn't valid :

enum XMLHttpRequestResponseType {
  "",
  "arraybuffer",
  "blob",
  "document",
  "json",
  "text"
};

The issue is that the XhrAdapter is used by Axios when making requests from the client-side / in the browser. If Axios is on the server-side, the HttpAdapter will be used. The XhrAdapter will need to make XMLHttpRequests but the server can make HttpRequests, so there are TONS of posts about handling streams in Node with Axios, since Node is a backend solution.

It doesn't appear to be possible to stream results with Axios on the client-side. fetch() may be the only option.

AskYous
  • 4,332
  • 9
  • 46
  • 82
Torc
  • 1,148
  • 6
  • 20
  • 43
  • Thanks for the detailed answer. Is there a benefit to using `stream` over `arraybuffer`? This answer suggests `arraybuffer` is better than `blob` for binary images (https://stackoverflow.com/a/60461828/144088) but is there an advantage to `stream` over `arraybuffer` for binary images? – Crashalot Apr 25 '21 at 08:10
  • An [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) has a fixed length and cannot be manipulated. [Streams](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) allow for manipulation by piping contents to another API mid-stream. I am not positive, but I believe that an ArrayBuffer also would require an object to be fully loaded into memory before sending a chunk of data, whereas a Stream sends a packet as soon as it can. – Torc Apr 25 '21 at 15:34
  • Thanks for the reply. So you can use streams when downloading an image like ones from the Twitter AP (with backend code)? They're not required for live streams of data? – Crashalot Apr 25 '21 at 20:20
  • If you are using **axios** and have direct access to Twitter's backend, then you can define a stream with **axios**. If you are requesting access to the image over HTTP, then you will have to use an `XMLHttpRequest` which does not support a stream. The issue on GitHub is still open, but the comments show some people's solutions. The `fetch` API is probably the best solution right now (without using a 3rd party solution) since that is meant to provide a readable stream as a response body type. – Torc Apr 25 '21 at 20:35
  • Thanks for the fast response. To clarify, you're saying `axios` for downloading images from Twitter will not work? Which GitHub issue are you referring to? Thanks for your help! – Crashalot Apr 25 '21 at 21:12
  • [Axios Issue 479](https://github.com/axios/axios/issues/479) – Torc Apr 25 '21 at 21:14
  • Downloading images can work, but I'm just saying that you can't define a `stream` response body type with **axios** right now. You can download an image with axios as a blob or some other data structure, but in order to stream the bytes you will need to use some other solution like the `fetch` API – Torc Apr 25 '21 at 21:17
  • Hi @Torc. I just sent a message, but it seems we missed each other. Could you please email info -at- hotpot dot ai? Yes, we need guidance (no coding) on questions like this: https://stackoverflow.com/questions/67225319/how-to-download-remote-image-then-upload-image-as-an-image-file-for-form-submiss. This is for helping people use our AI services via Twitter bots. – Crashalot Apr 27 '21 at 06:47
-1

I am using Axios library with Twitter Stream API but only with GET Method. Beginning of the code:

const streamTweets = async (socket,token) => {
    let stream;
    
    const headers = {
        'Authorization':"Bearer "+BEARER_TOKEN,
    }
    const options = {
        method:"GET",
        url:streamURL,
        headers:headers,
        timeout:31000,
        stream:true,
        responseType:"stream"
    };

    try {
        console.log("Uruchamiam funkcję streamTweets");
        // const stream = await axios(options);
        axios(options).then(respobj => {

I believe both options - stream and responseType - must be set. However if you work with Twitter Stream API using socket.io library be aware it might be buggy as after socket emit event no code is executed afterwards. I pointed that out to Socket developers but 6 months are passed and nothing there.

Sebastian
  • 448
  • 4
  • 14