Sunday, 24 March 2019

axios onUploadProgress and onDownloadProgress not working with CORS

I have a server written in Node.js, and a web client running in the browser. The client shall upload and download some files from and to the server. The server is not the one that originally delivers the client, so we have a cross-domain situation here.

The server uses the cors middleware to enable cross-domain requests. Since I am also using a number of custom headers, I use it with a configuration like this:

api.use(cors({
  origin: '*',
  allowedHeaders: [ 'content-type', 'authorization', 'x-metadata', 'x-to' ],
  exposedHeaders: [ 'content-type', 'content-disposition', 'x-metadata' ]
}));

In contrast, the client is using axios, and the code to upload a file looks like this:

await axios({
  method: 'post',
  url: 'https://localhost:3000/api/v1/add-file',
  data: content,
  headers: {
    // ...
  }
});

So far, everything works as expected, and it especially works with the CORS thing.

Now I would like to track the progress of the upload, and hence I add the onUploadProgress callback to the axios call, as suggested by its documentation:

await axios({
  method: 'post',
  url: 'https://localhost:3000/api/v1/add-file',
  data: content,
  headers: {
    // ...
  },
  onUploadProgress (progressEvent) {
    console.log({ progressEvent });
  }
});

If I now run the client, the upload still works – but the onUploadProgress callback is never called. I have read that not all browsers support this (internally this just binds to the onprogress event of the underlying XmlHttpRequest object), but latest Chrome should be able to do it (and if I try a different setup, where CORS is not involved, everything seems to work). So I assume that it's a CORS issue.

I have read that as soon as you add a listener to the onprogress event, a preflight request will be sent. This in turn means that the server has to accept OPTIONS requests. For that, I added the following code on the server, before the aforementioned call to api.use:

api.options('*', cors({
  origin: '*',
  methods: [ 'GET', 'POST' ],
  allowedHeaders: [ 'content-type', 'authorization', 'x-metadata', 'x-to' ],
  exposedHeaders: [ 'content-type', 'content-disposition', 'x-metadata' ],
  optionsSuccessStatus: 200
}));

The result: The upload still works, but still no onUploadProgress event is raised. So I assume that I am missing something, related to CORS. The question is just: What am I missing?

I have also tried to re-run the same setup with a larger file (almost 2 GBytes instead of a few KBytes), but the result is the same. Does anyone have an idea what I am doing wrong here?



from axios onUploadProgress and onDownloadProgress not working with CORS

No comments:

Post a Comment