I have a node project and something very strange is happening. I have a routes file that has all of my routes and I import that on my server.js file. When I import the routes file. A get request of that route does not work at all, but when I paste that same route on the server.js it works as expected. Other routes in the file work correctly, but this one in particular does not work as expected. Code below. Thanks for any help.
server.js
require('./server/routes/mainRoutes.js')(app);
mainRoutes (this will not work):
app.get('/accounts',function(req,res){
res.json({Test:'name'});
});
Now if I put that /accounts route on the main server.js it will work. For some reason it never works in the imported mainRoutes file.
I'm not sure why it's not working, It can help if you share the app initiation (I understand you use express?) and your use of app.listen.
Anyway, a best practice would be to use app.use, as follows:
server.js:
var routes = require('./server/routes/mainRoutes.js');
var express = require('express');
var app = express();
app.use('/', routes.app);
var server = app.listen(somePort, someIP, function() {
console.log('Listening...');
});
mainRoutes.js:
var express = require('express');
var app = express();
app.get('/accounts',function(req,res){
res.json({Test:'name'});
});
module.exports = {
app: app
};
Related
Let's say I have an Express app defined in a file, say server.js like this:
const app = express();
app.use('/foo', foo);
app.use('/bar', bar);
module.exports = app;
I import this Express app in another file, say index.js:
const app = require('./server');
const port = process.env.PORT || 3000;
const listen = (port) => {
app.listen(port, () => {
console.log(`Backend listening on port ${port}!`);
});
};
listen(port);
Now, the routes that are available for this app are /foo and /bar.
Is there a way to edit configuration in the index.js file so that the routes become /api/foo and /api/bar? Without touching server.js file.
Use case:
I have a Nuxt.js app with a backend that is loaded into the Nuxt app via serverMiddleware property in nuxt.config.js like this:
serverMiddleware: [
...
{ path: '/api', handler: '~/server.js' },
],
This has the effect similar to what I described above: it imports the express app from server.js app and prepends all its routes with /api.
However, often I don't want to develop the frontend part of the Nuxt app, I just want to do changes on the backend. For this purpose I have a helper file like index.js above, which runs backend only. (Frontend often takes long time to compile, that's why I don't want to compile it when I don't need to.)
This creates a problem that all the routes are slightly different - they lack the /api at the beginning. The routes are being used in different tools like Postman etc. and suddenly they wouldn't work.
My current solution is to define index.js file in the same way as server.js file with all routes defined like I want them - instead of app.use('/foo', foo); there's app.use('/api/foo', foo); etc. but this has its own problems, e.g. if I change server.js I have to change index.js. I am looking for something more elegant.
According to the express 4.0 docs https://expressjs.com/en/4x/api.html#app.use you can use an application instance the same as you would a router. In short, just use the export of your server.js as a middleware at the route in which you want to insert it, as opposed to directly calling .listen() on it.
Here is some demo code that worked for me:
const express = require('express');
const app_inner = express();
app_inner.use('/foo', (req,res) => res.send('foo'));
const app_outer = express();
app_outer.use('/foo2', app_inner);
app_outer.listen(9999);
// web browser at localhost:9999/foo2/foo returns 'foo' as expected
I am new to javascript and node.js I am learning online and trying to create a cms using node.js, express and sqlite. Before going to details I will give you guys my directory structure.
rootdir
node_modules
public
css (generic styling files)
vendor (bootstrap and js files)
routes
defaultRoutes.js
views
default
index.handlebars
partials
default
(header and footer files)
layouts
main.handlebars
app.js
package-lock.json
package.json
app.js is where the server is created and defaultRoutes are for routes. When I run
//code in defaultRoutes.js
const express = require('express');
const router = express.Router();
router.use((req,res) => {
res.render('default/index');
});
module.exports = router;
and
//code in app.js
//Routes
const defaultRoutes = require('./routes/defaultRoutes');
app.use(defaultRoutes);
the page renders but when I change the router.use in defaultRoutes to router.get the browser throws cannot GET error.
Can anyone explain why this is happening?
You need to define a route when using router.get(). router.use() can work for any route, but to define a route with router.get() you can add the route like this:
//code in defaultRoutes.js
const express = require('express');
const router = express.Router();
router.get('/', (req,res) => {
res.render('default/index');
});
module.exports = router;
I am trying to understand what is going on when I use module.exports with a variable in a model view controller type project. I just do not understand what the book means by using it in this way
var express = require("./config/express.js");
var app = express();
app.listen(3000);
module.exports = app; // my problem is right here what is it doing
console.log("Server running at http://localhost:3000/");
my config/ express file is also here
var express = require("express");
module.exports = function()
{
var app = express();
require("../app/routes/index.server.routes.js")(app);
return app;
}
The first example is exporting the Express app directly and the second example is exporting a function that returns the Express app.
This means that in the first example, require(...) will return app. In the second example, you would need to do require(...)() to have app returned.
In an attempt to build a truly modular express app (one that can run stand alone or as a part of another app) I need to find out the cleanest way to find the mount path from inside the subapp. For a short example, lets say that there are two files: main.js and subapp.js
main.js
var express = require('express');
var app = express();
var localApp = express();
var subapp = require('./subapp');
app.use('/foo', subapp);
app.use('/bar', localApp);
console.log(localApp.mountpath); // yes, this prints '/bar' as expected
...
subapp.js
var express = require('express');
var app = express();
var truePath = app.mountpath; // I wish this would point to '/foo', but instead points to '/'
...
module.exports = app;
What is the best way (as in cleanest) to find the mountpath from inside the module? I'm doing this trying to solve this problem: Access to mountpath variable from inside a template using express in a non hardwired way.
As shown in the example, tried already with app.mountpath without success
As answered by alsotang, this is actually a problem of execution sequence, but it can be solved in what I think is a clean way. There is an event that is fired after the module is mounted, so you can do:
var truePath = = "/";
app.on('mount', function (parent) {
truePath = app.mountpath;
});
Where in real life truePath could be app.locals.truePath, so it can be accessed from inside the views.
eh..It's a problem of execution sequence.
In your subapp.js, the app.mountpath statement is before module.exports = app.
But only you export the app, then the app be mounted, then it would be set the mountpath property.
so, you should retrieve mountpath after the app be mounted by outer express.
My suggestion are two:
set the mountpath in your subapp.js. And outer express read this property.
perhaps you think 1 is not truly modular. so you can alternatively define a config file. and both main.js and subapp.js read mountpath from the config.
Try req.baseUrl:
app.js
var express = require('express');
var app = express();
var foo = require('./foo');
app.use('/foo', foo);
app.listen(3000);
foo.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
console.log(req.baseUrl); // '/foo'
res.send('foo');
});
module.exports = router;
I am new to Node.js and Express and have tried to go through some of the tutorials. I am able to get basic routing working one level deep (e.g., http://localhost/help), but I'm having trouble getting it to work two levels deep (e.g., http://localhost/help/test).
Here are the relevant lines in app.js:
var help = require('./routes/help');
// also tried this
//var help_test = require('./routes/help/test');
var app = express();
app.use('/help', help);
app.use('/help/test', help.test);
// also tried this
//app.use('/help/test', test);
//app.use('/help/test', help_test);
Under the routes directory I have two files: index.js and test.js.
The index.js consists of:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('help');
});
module.exports = router;
The test.js file consists of:
var express = require('express');
var router = express.Router();
router.get('/test', function(req, res) {
res.send('help test!');
});
module.exports = router;
Right now I can't start the server due to the configuration in app.js, but any changes I make so that I can start it results in a 404 error when I try to hit http://localhost/help/test
I think some of your confusion is coming from the require in app.js. Let's look at this line:
var help = require('./routes/help');
That line loads the module in routes/help.js. This file is non-existent In your current configuration. Rename your ./routes/index.js file to ./routes/help.js.
Since the above file will only handle routes prefixed with /help and not /help/test, will need to have an additional require:
var help_test = require('./routes/test');
Your app.js file should now have the following:
var help = require('./routes/index');
var help_test = require('./routes/test');
var app = express();
app.use('/help', help);
app.use('/help/test', help_test);
It should be noted that since your help_test module defines a path at /test, and you "use" it at /help/test, the final path of that route will be: /help/test/test.
Tim's answer got me on the right track, but I ended up with a slightly different solution using his answer that I wanted to post:
In app.js I have:
var help = require('./routes/help');
var help_test = require('./routes/help/test');
....
app.use('/help', help);
app.use('/help/test', help_test);
Under the /routes directory I have this structure:
routes
|-- help
|-- index.js
|-- test.js