Search code examples
node.jsexpressfeathersjsfileserverfeathers-hook

integrate tus-node-server into feathersjs with express


I have an existing and properly working Feathers project is in the most recent feathers cli ("Buzzard") structure. Now I am trying add tus-node-server as upload server. As you can find in the link their instructions to set it up as express middleware are as follows:

const tus = require('tus-node-server');
const server = new tus.Server();
server.datastore = new tus.FileStore({
    path: '/files'
});

var app = express();
const uploadApp = express();
uploadApp.all('*', server.handle.bind(server));
app.use('/uploads', uploadApp);
app.listen(port, host);

Following these instructions I tried adding this to my app.js file:

// tus node server
const tus = require('tus-node-server');
const tusServer = new tus.Server();
tusServer.datastore = new tus.FileStore({
  path: '../uploads'
});

const uploadApp = express();
uploadApp.all('*', tusServer.handle.bind(tusServer));
app.use('/uploads', uploadApp);

For completeness I give the entire app.js file:

const path = require('path');
const favicon = require('serve-favicon');
const compress = require('compression');
const cors = require('cors');
const helmet = require('helmet');
const logger = require('winston');

const feathers = require('@feathersjs/feathers');
const configuration = require('@feathersjs/configuration');
const express = require('@feathersjs/express');
const socketio = require('@feathersjs/socketio');

const middleware = require('./middleware');
const services = require('./services');
const appHooks = require('./app.hooks');
const channels = require('./channels');

const sequelize = require('./sequelize');

const authentication = require('./authentication');

const app = express(feathers());

// Load app configuration
app.configure(configuration());
// Enable CORS, security, compression, favicon and body parsing
app.use(cors());
app.use(helmet());
app.use(compress());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(favicon(path.join(app.get('public'), 'favicon.ico')));

// Host the public folder
app.use('/', express.static(app.get('public')));

// Set up Plugins and providers
app.configure(express.rest());
app.configure(socketio({
  wsEngine: 'uws',
  timeout: 120000
}));
app.configure(sequelize);

// Configure other middleware (see `middleware/index.js`)
app.configure(middleware);
app.configure(authentication);
// Set up our services (see `services/index.js`)
app.configure(services);
// Set up event channels (see channels.js)
app.configure(channels);

// tus node server
const tus = require('tus-node-server');
const tusServer = new tus.Server();
tusServer.datastore = new tus.FileStore({
  path: '../uploads'
});

const uploadApp = express();
uploadApp.all('*', tusServer.handle.bind(tusServer));
app.use('/uploads', uploadApp);

// Configure a middleware for 404s and the error handler
app.use(express.notFound());
app.use(express.errorHandler({ logger }));

app.hooks(appHooks);

module.exports = app;

I get this error:

# npm start

> [email protected] start /home/usr/api_server
> node src/

/home/usr/api_server/node_modules/@feathersjs/express/lib/index.js:11
    throw new Error('@feathersjs/express requires a valid Feathers application instance');
    ^

Error: @feathersjs/express requires a valid Feathers application instance
    at feathersExpress (/home/usr/api_server/node_modules/@feathersjs/express/lib/index.js:11:11)
    at Object.<anonymous> (/home/usr/api_server/src/app.js:70:19)
    at Module._compile (module.js:660:30)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
    at Module.require (module.js:604:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/home/usr/api_server/src/index.js:3:13)
    at Module._compile (module.js:660:30)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
    at Function.Module.runMain (module.js:701:10)
    at startup (bootstrap_node.js:193:16)
    at bootstrap_node.js:617:3

How should this be setup? How to integrate this best into Feathers? From this I get the impression that Services & Hooks setup is preferable to a setup as middleware!?


Solution

  • For reference, the solution from the GitHub issue is to use require('@feathersjs/express').original or require('express') to initialize the application:

    const createExpressApp = require('express');
    const uploadApp = createExpressApp();
    
    uploadApp.all('*', tusServer.handle.bind(tusServer));
    app.use('/uploads', uploadApp);
    

    Or by accessing require('@feathersjs/express').original (the express module @feathersjs/express relies on) in your app like this:

    const uploadApp = express.original();
    
    uploadApp.all('*', tusServer.handle.bind(tusServer));
    app.use('/uploads', uploadApp);