Im having node app which using express i've server.js app.js etc
I need to use as middelware the following code
var upload = multer({
storage: storage
});
app.use(upload.single('file'));
app.use('/', rot, function (req, res, next) {
next();
});
But before the var upload = multer... I want to run the following
code
var mkdirSync = function (path) {
try {
fs.mkdirSync(path);
} catch(e) {
if ( e.code != 'EEXIST' ) throw e;
}
}
mkdirSync( 'uploads/');
How should I do it nicely? add the code of mkdir before the upload multer
You can create another middleware for this purpose, since app.use accepts multiple middleware functions.
app.use(function(req, res, next) {
fs.mkdir(path, function(e){
if(!!e && e.code !== 'EEXIST'){
next(e);
return;
}
next();
});
}, upload.single('file'));
The above code should work. When you pass an error into the next middleware, express will know to skip all the following middleware functions and go straight to the error handler.
EDIT: I would recommend using the non-sync version of mkdir, and avoiding the try/catch block altogether.
EDIT 2: Maybe I am mistaken, and all you are looking to do is make sure the storage directory exists? If this is the case then simply doing the following will work:
mkdirSync(storage);
var upload = multer({
storage: storage
});
app.use(upload.single('file'));
app.use('/', rot, function (req, res, next) {
next();
});
Its better to do like this.
//dir.js
exports.makeDir = function(path) {
console.log(path);
try {
fs.mkdirSync(path);
} catch (e) {
if (e.code != 'EEXIST') throw e;
}
}
And in your app.js
var varMkDir = require('./dir');
app.use(varMkDir.makeDir('uploads/'));
EDIT :
app.use(function(){
varMkDir.makeDir('uploads/');
})
Related
I would like to be able to set an app.use() path depending on the domain my Node.JS server receives the request as to return one set of files or another. I have tried with the following code, but when testing the files are never returned to the client.
app.use('/scripts', (req, res) => {
if (req.host == `mysite.com`) {
express.static(path.resolve(__dirname, 'landing', 'frontend/scripts'));
} else if (req.host == `admin.mysite.com`) {
express.static(path.resolve(__dirname, 'admin', 'frontend/scripts'));
}
});
I am using express as a dependancy to try and do this, but no avail, I am willing to try other packages if this can help solve my issue.
Not tested, but I would assume you can keep a reference to each static route and then just forward the requests, don't forget next so that normal 404 can be handled.
eg.
const static1 = express.static(path.resolve(__dirname, 'landing', 'frontend/scripts'));
const static2 = express.static(path.resolve(__dirname, 'admin', 'frontend/scripts'));
app.use('/scripts', (req, res, next) => {
if (req.hostname == `mysite.com`) {
static1(req, res, next);
} else if (req.hostname == `admin.mysite.com`) {
static2(req, res, next);
} else res.end(`host: ${req.hostname} not found`);
});
I am trying to implement File Upload functionality using multer and Express Router. I defined an endpoint /batch_upload using router.use like below
api.js
router.use(
"/batch_upload",
upload.single("emp_csv_data"),
userController.processBatchUserInformation
);
in userController.js
exports.processBatchUserInformation = async (req, res) => {
console.log(req.file);
if (req.method == "POST") {
try {
console.log("Upload route reached - POST");
console.log(req.file);
console.log(req.file.path);
return res.send(req.file);
} catch (err) {
console.log("Error Occurred");
return res.send(err);
}
}
};
In the FileUploader.js, I defined the upload variable and multer options like below
var multer = require("multer");
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "uploads");
},
filename: (req, file, cb) => {
return cb(null, file.fieldname + "-" + Date.now());
}
});
exports.upload = multer({ storage: storage });
Finally, in the app.js I used the route using
app.use('/user',user_routes)
But when I send a file to http://localhost:5000/user/batch_upload, I get an undefined response for req.file
Irony is that I have the exact implementation in a sample test project and everything seems fine. I don't understand what am I missing. If you see something that seems off, please help me fix it.
So, the reason behind the file not being uploaded was that I did not add Content-type:multipart/form-data in the headers. Thank you guys for trying to help. I appreciate it.
Here below there are two servers and two gqlServers. All combinations of them work.
The challenge is to extend express with some additional predefined code patterns shared across several apps, exposed through additional methods.
Which combination of a server and gqlServer is considered best practice and best for performance?
server:
server_A is a function that returns a class
server_B is a function that returns a function
gqlServer:
gqlServer_01 uses req.pipe
gqlServer_02 has the original express() passed into it
function gqlServer_01(options) {
let gqlApp = express();
gqlApp.use(options.route, function(req, res, next) {
res.send('gqlServer 01');
// next();
});
gqlApp.listen(8001, err => {
if (err) throw err;
console.log(`>> GQL Server running on 8001`);
});
}
function gqlServer_02(app, options) {
app.use(options.route, function(req, res, next) {
res.send('gqlServer 02');
// next();
});
}
// THIS SERVER ?
function server_A(config = {}) {
config = deepmerge(def_opt, config);
let app = express();
app.get('/', function(req, res, next) {
res.send('root');
// next();
});
class Server {
constructor(opt) {
this.opt = opt;
}
gql(props = {}) {
// THIS GQL SERVER ?
gqlServer_01({ route: '/gql-01' });
app.use('/gql-01', function(req, res) {
req.pipe(request(`http://localhost:8001/gql-01`)).pipe(res);
});
// OR THIS GQL SERVER ?
gqlServer_02(app, { route: '/gql-02' });
}
}
app.listen(8000, err => {
if (err) throw err;
console.log(`>> Server running on 8000`);
});
return new Server(app, config);
}
// OR THIS SERVER ?
function server_B(config = {}) {
config = deepmerge(def_opt, config);
let app = express();
app.get('/', function(req, res, next) {
res.send('root');
// next();
});
app.gql = function(props = {}) {
// THIS GQL SERVER ?
gqlServer_01({ route: '/gql-01' });
app.use('/gql-01', function(req, res) {
req.pipe(request(`http://localhost:8001/gql-01`)).pipe(res);
});
// OR THIS GQL SERVER ?
gqlServer_02(app, { route: '/gql-02' });
};
app.listen(8000, err => {
if (err) throw err;
console.log(`>> Server running on 8000`);
});
return app;
}
The goal is to have the best solution in order to create an npm package out of this and reuse the methods over several projects easily. The project was highly simplified for the sake of clarity.
I don't think you will have performance issues in any of these examples, so the question remains which of them is more modular.
If you are willing to make an npm package out of these, you shouldn't be calling express() inside your server code. Instead you should be passing the app as a parameter. This will allow you to reuse existing express apps initialized elsewhere. For this reason I would go for gqlServer_02
You also want to create a new server each time you call the module function, so I'd go with server_A for this reason. However it needs to receive the express app as parameter, in order to reuse existing express objects. I would also put the app.listen call inside a function in the Server class.
Exploring express framework. Learning the express.static middleware but it doesn't function the way I expect it to.
Code:
const express = require("express");
const app = express();
app.use((req, res, next) =>{
express.static('public');
next();
});
app.use((req, res) => {
console.log("Starting first middleware");
});
app.listen(3000);
The above code doesn't serve my static html files in the publlic folder. The public folder is on the same directory as this JS file, and when I for instance use the URL http://localhost:3000/home.html to try to access the home.html file in the public folder I cannot access it.
When I switch up the order that the express.static is last it does serve my static html file in the public folder.
Code:
app.use((req, res, next) => {
console.log("Starting first middleware");
next();
});
app.use(express.static('public'));
Question:
Why doesn't my app in the first code example serve the static files?
express.static is a function that returns another function (middleware), and Express middlewares expect 2 or 3 parameters (req, res[, next]).
When it is used as a callback, like this:
app.use(express.static('public'));
you don't need to explicitly provide parameters to it, since app.use will provide them for you.
However, when you use it yourself, you need to explicitly call the function with its parameters:
app.use((req, res, next) =>{
express.static('public')(req, res, next);
next();
});
In your first example, you were generating the middleware, but not executing it.
There is a fundemental difference between the two snippets. You see the first one you are basically calling the function express.static with argument 'public' inside the callback function of a middleware you declared, this only will return a function that will not be used in next middlewares as no arguments passed to it; the req object should be passed to it. However in the second one this will return a function that can use the req object which is passed along with the res normally in the app.use. Take a look at some of the source code of the 'static' function to get an idea :
function serveStatic (root, options) {
if (!root) {
throw new TypeError('root path required')
}
if (typeof root !== 'string') {
throw new TypeError('root path must be a string')
}
// copy options object
var opts = Object.create(options || null)
// fall-though
var fallthrough = opts.fallthrough !== false
// default redirect
var redirect = opts.redirect !== false
// headers listener
var setHeaders = opts.setHeaders
if (setHeaders && typeof setHeaders !== 'function') {
throw new TypeError('option setHeaders must be function')
}
// setup options for send
opts.maxage = opts.maxage || opts.maxAge || 0
opts.root = resolve(root)
// construct directory listener
var onDirectory = redirect
? createRedirectDirectoryListener()
: createNotFoundDirectoryListener()
return function serveStatic (req, res, next) { // the funciton returned
if (req.method !== 'GET' && req.method !== 'HEAD') {
if (fallthrough) {
return next()
}
// method not allowed
res.statusCode = 405
res.setHeader('Allow', 'GET, HEAD')
res.setHeader('Content-Length', '0')
res.end()
return
}
var forwardError = !fallthrough
var originalUrl = parseUrl.original(req)
var path = parseUrl(req).pathname
// make sure redirect occurs at mount
if (path === '/' && originalUrl.pathname.substr(-1) !== '/') {
path = ''
}
// create send stream
var stream = send(req, path, opts)
//rest of code...
I'm working in a restful service using express.js and i want to enhance the req and res variables so for example you could write something like
app.use(function (req, res, next) {
res.Ok = function (data) {
res.status(200).send(data);
};
res.InternalError = function (err) {
res.status(500).send(err);
};
});
And later
router.get('/foo', function (req, res) {
res.Ok('foo');
})
This will send 'foo' in the body of the response and set the status code to 200 and is working perfectly.
My first question is if it is possible to add such functionality without a middleware function, lets say in a property or the prototype of the app variable?
The second question is if there are performance issues if you add many functionality with middleware functions at the app level. Are this functions attached to the request and response object per request or once on the application startup?
I know the Sails framework already do this but I'm wondering if they use middleware functions as well.
I keep digging and turns out that the request and response object are exposed in express using the __proto__ property.
var express = require('express'),
app = express();
app.response.__proto__.foo = function (data) {
this.status(200).send(data);
};
And later in the router
router.get('/foo', function (req, res, next) {
res.foo('test');
});
This will print test in your browser so it is possible to add functionality without using any middleware.
Note: I'm sure there are some drawbacks to this approach (overwriting express predefined properties, for example) but for testing purposes and adding very simple functionality I think is slightly better in terms of performance.
I'm not aware of any other way than using middleware. But in my opinion you could do the following to achieve nearly the same thing.
// Some Route
router.get('/foo', function(req, res, next) {
// ...
if(err) {
res.status(500);
return next(err);
}
return res.send('ok');
});
// Another route
router.get('/bar', function(req, res, next) {
// ...
if(badUserId) {
res.status(400);
return next('Invalid userId.');
}
req.result = 'hello';
return next();
});
router.use(function(req, res) {
// I prefer to send the result in the route but an
// approach like this could work
return res.send(req.result);
});
// Error Middleware
router.use(function(err, req, res, next) {
if(res.statusCode === 500) {
// Log the error here
return res.send('Internal server error');
} else {
return res.send(err);
}
});