CORS Error when using TUS to direct creator upload

I’m trying to use the TUS JS Client to upload a video to Cloudflare Stream via the Direct Creator Upload method but am being plagued with CORS errors whilst in an Angular 12 Web Application, with a Node.js Backend GraphQL API.

In the first step of the user uploading the video, I send a request to our Backend API with a few bits of information including:

Video Title, Video Description, Video Size in bytes, and the ID of the account the video is to be uploaded to (nothing to do with CF Stream).

In response to that request, the Node server completes the following request:

const result = await axios.post(
        `https://api.cloudflare.com/client/v4/accounts/${cloudflareStreamAccountID}/stream?direct_user=true`,
        {},
        {
          headers: {
            "Tus-Resumable": "1.0.0",
            "Upload-Length": args.size,
            Authorization: `bearer ${cloudflareStreamToken}`,
          },
        }
      );

In the response sent back to the Angular Frontend after completing this request, I get the ‘direct creator upload’ secret which looks something like this:

https://upload.videodelivery.net/f65014bc6ff5419ea86e7972a047ba22

I then use that URL in the follow TUS-JS-CLIENT request:

const videoFile = this.video;
    let chunkSize = 0;
    if (this.videoSize < 5242880) {
      chunkSize = this.videoSize;
    } else {
      chunkSize = 5242880;
    }

    const upload = new Tus.Upload(videoFile, {
      endpoint: stepOneData.url,
      retryDelays: [0, 3000, 5000, 10000, 20000],
      chunkSize: chunkSize,
      metadata: {
        filename: this.videoName,
        filetype: this.video.type
      },
      onError: function (err) {
        console.error('Video Upload Failed due to: ' + err);
      },
      onProgress: function (bytesUploaded, bytesTotal) {
        const percentage = (bytesUploaded / bytesTotal * 100).toFixed(2);
        console.log(bytesUploaded, bytesTotal, percentage + '%');
      },
      onSuccess: function () {
        console.log('Download %s from %s', upload.file['name'], upload.url);
      }
    });

    upload.findPreviousUploads().then(function (previousUploads) {
      if (previousUploads.length) {
        upload.resumeFromPreviousUpload(previousUploads[0]);
      }

      upload.start();
    });

I’m following all documentation that I can find by the letter, but still I get the following CORS Errors in the Frontend:

Access to XMLHttpRequest at 'https://upload.videodelivery.net/tus/xxxxxxxxxxxxxxx?tusv2=true' from origin 'https://dev.mywebsite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Whyyyyyyyyyyyyyyy?

What am I missing? We’re meant to be deploying this to 200+ users within the next 48 hours! :scream: :scream: :scream:

3 Likes

There are many posts here about TUS and CORS. Many of them say to not upload to the videodelivery.net URL, but to use the endpoint in your domain.

I don’t use Stream (or TUS, for that matter), so I’m not sure where all this is configured.

https://community.cloudflare.com/search?q=tus%20cors

2 Likes

Yes, this is a very common misunderstanding: when you are using Direct Creator Uploads, the url you set in tus should be to the endpoint on your server.

Your server should return the videodelivery.net URL obtained from the Stream API as a Location header. This is illustrated in the demo JavaScript code here: https://developers.cloudflare.com/stream/uploading-videos/direct-creator-uploads#using-tus-recommended-for-videos-over-200mb

3 Likes

Apologies but I’m not understanding what you’re saying.

“the url you set in tus should be to the endpoint on your server” - This means that TUS will attempt to upload the file to my GraphQL Node server - Not Cloudflare Stream. How does this help? Is your answer that CF Stream only accepts file uploads from a backend node server?

There is zero documentation or examples of what happens once " Your server should return the videodelivery.net URL obtained from the Stream API as a Location header.".

Even if our Node server sent this as a header to the frontend - then what?

Our Node server already sends the videodelivery.net URL to the frontend. If I’m not meant to use it in the TUS client, where is it used? There is no examples of this happening anywhere

2 Likes

“This means that TUS will attempt to upload the file to my GraphQL Node server”

TUS won’t try to upload the actual file to your server. The url that tus actually uploads the file to is the url it finds in the “Location” header.

Let’s say you have a service at myorigin.com/newUpload that calls the Stream API and returns the “Location” header with the videodelivery.net URL.

When you configure tus to upload to myorigin.com/newUpload, it only means the very first request will goto the myorigin.com. tus will then read the Location header and the actual upload of the file will occur to the url in the location header.

3 Likes