tus-node-server icon indicating copy to clipboard operation
tus-node-server copied to clipboard

Access-Control-Allow-Credentials' header in the response is ''

Open Shooshte opened this issue 2 years ago • 4 comments

I am following along with the docs for setting up a standalone express server and ran into an issue. When I try to upload files from localhost using uppy alongside uppy-tus I get the following error:

upload:1 Access to XMLHttpRequest at 'http://localhost:8080/files/' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

This is my server implementation:

import 'dotenv';
import tus = require('tus-node-server');

const server = new tus.Server();

server.datastore = new tus.S3Store({
  path: '/files',
  bucket: 'mavrica',
  accessKeyId: process.env.NX_WASABI_KEY,
  secretAccessKey: process.env.NX_WASABI_SECRET,
  region: 'eu-west-1',
  partSize: 1024, // each uploaded part will have 1MB,
  tmpDirPrefix: 'tus-s3-store',
});

const host = 'localhost';
const port = 8080;

// @ts-expect-error: ts-node-server imports listed arguments types are wrong according to their docs
server.listen({ host, port }, () => {
  console.log(
    `[${new Date().toLocaleTimeString()}] tus server listening at http://${host}:${port}`
  );
});

This is my FE uppy implementation:

import React from 'react';
import Uppy from '@uppy/core';
import Tus from '@uppy/tus';
import { DragDrop } from '@uppy/react';

const uppy = new Uppy({
  restrictions: { allowedFileTypes: ['image/*'], maxNumberOfFiles: 1 },
  autoProceed: true,
});

uppy.use(Tus, {
  chunkSize: 1024,
  endpoint: 'http://localhost:8080/files/',
  retryDelays: [0, 1000, 3000, 6000, 12000, 24000],
  withCredentials: true,
});

uppy.on('complete', (result) => {
  const url = result.successful[0].uploadURL;
  console.log('url:', url);
});

const Upload = () => {
  return (
    <div>
      <DragDrop
        uppy={uppy}
        locale={{
          strings: {
            // Text to show on the droppable area.
            // `%{browse}` is replaced with a link that opens the system file selection dialog.
            dropHereOr: 'Drop here or %{browse}',
            // Used as the label for the link that opens the system file selection dialog.
            browse: 'browse',
          },
        }}
      />
    </div>
  );
};

export default Upload;

Can somebody help me out please, can't find any additional info in the docs.

Shooshte avatar Jun 19 '22 09:06 Shooshte

I usually use 'cors' npm package for handling CORS. If you go this route I think setting 'credentials: true' in configuration should help.

https://www.npmjs.com/package/cors#configuration-options

Is there a reason you use 'withCredentials: true' in Uppy? Disabling this should also solve your issue.

mitjap avatar Jun 19 '22 17:06 mitjap

Indeed, withCredentials is not wanted in this setup. You also shouldn't define chunkSize unless you absolutely must. It's highly inefficient to set it so low. The default is Infinity and Tus will try to upload the whole file with one connection.

Murderlon avatar Jun 20 '22 10:06 Murderlon

@Shooshte did you solve this issue?

mitjap avatar Jul 17 '22 00:07 mitjap

You can manually add the 'Access-Control-Allow-Credentials' header in the OPTIONS request by using a middleware. In express, I'd do the following:

const app = express()
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Credentials', 'true')
  // can add more CORS headers here
  next()
});

abhi12299 avatar Jul 29 '22 06:07 abhi12299

Closes this question as stale

Murderlon avatar Dec 13 '22 13:12 Murderlon