Making a conditional app.use() with Node and Express? - javascript

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`);
});

Related

How to modularize an express app - with a function, a class and req.pipe?

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.

Meteor Server Side Redirect Webapp

Hi guys I am trying to do a redirect in meteor server. So I do it like this
WebApp.connectHandlers
.use(function (req, res, next) {
console.log(req)
if (req.url === '/') {
// 307 Temporary Redirect
console.log(req)
res.writeHead(307, {
Location: '/login'
})
res.end()
} else {
// Let other handlers match
next()
}
})
However it redirects to http://login instead of http://localhost:3000/login
I also tried Location: 'http://localhost:3000/login' and
res.redirect()
But still got the same. What am I doing wrong in here?

Node app.js use function how its recommended

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/');
})

It is possible to enhance the express.js req and res variables without using a middleware function?

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);
}
});

Express js routes url to correct page

URL pattern is www.example.com/product-name/pid_010101. URL's first segment is Product name and second segment is Product number. My app router code is below
app.get("/:name?/:id", routes.index);
Now my all urls redirect to same page. For example some url like www.example.com/homepage/banner.html also redirect to www.example.com/product-name/pid_010101
Need to add some Filters in router. How to route the url to correct page?
I assume your routes will be:
/coffeemaker/pid_0101222
/bluemarker/pid_121121
etc. ?
You can use regular expressions for this OR
this is an example of in method filtering:
app.get('/rest/:collection', function(req, res) {
return routes.rest[req.params.collection](req, res);
});
in routes object:
exports.rest = {
tweets: function(req, res) {
return twitter.data.load(function(data) {
return res.json(data);
}, config.site.tag, req);
},
pics: function(req, res) {
return instagram.data.load(function(data) {
return res.json(data);
}, config.site.tag, req);
},
repos: function(req, res) {
return github.data.load(function(data) {
return res.json(data);
}, req);
},
links: function(req, res) {
return delicious.data.load(function(data) {
return res.json(data);
}, config.site.tag, req);
}
};
:colection is then tweets, pics , or links string
Can you make a list of all your pages?
Maybe I can help you with your routes...
This is because of /homepage/banner.html complies to your route as well.
Therefore you must also specify those routes you want to trigger.
Say for example you have a welcome page.(/welcome/guest) or something like that.
You can add another route above the general route. specific for that page.
app.get("/welcome/guest", routes.welcome);
Now this is too much work for all your pages. So you can avoid this with a couple of techniques, one would be to put a static part in the url say:
app.get("/product/:name?/:id", routes.product);
I don't really get your problem. Is /homepage/banner.html a static page? Middlewares work like a filter, you can simply put express.static above express.router:
app.use(express.static('public'));
...
app.use(app.router);
app.get("/:name?/:id", routes.index);
banner.html is in (APP_DIR)/public/homepage/banner.html
Write own middleware function that handles the legacy URLs, and place it above the Express router.
app.use(function(req, res, next) {
if (legacySystemHandles(req.url)) {
// do legacy stuff
}
else next(); // pass to the next middleware function
});
app.use(app.router);

Categories