New to Node/Express, trying to figure out what the best way to make my server controllers organized and modular. I have app.js file with the following code.
var express = require('express');
var app = express();
// Launch Server
const PORT = process.env.PORT || 8888;
app.listen(PORT, function() {
console.log('Server running on port ' + PORT + '!');
});
// Render Static Views from the Public Directory/Views
app.use('/', express.static(__dirname + '/public/views/'));
// API
// var foo = require(bar);
I want to keep all of my API logic in apiController.js then require it into my app.js. What's the best way to do this?
Example GET Endpoint
app.get('/api', function(req, res) {
res.json({
success: true,
message: 'Hello World!'
});
});
Here is my project structure:
I like David Fang's solution, but I would go one step further and create an Express 4 router for your API routes. They're very composable and modular, as they can act as both routers and middleware, can be nested and imported neatly.
app.js
var apiRouter = require('./controllers/apiController.js');
app.use('/api', apiRouter);
apiController.js
var express = require('express');
var apiRouter = express.Router();
apirouter.get('/some/route', (req, res) => {
// some code...
})
module.exports = apiRouter;
Documentation: http://expressjs.com/en/api.html#router
Here's a simple method:
app.js
require('./controllers/apiController.js')(app);
apiController.js
module.exports = function(app) {
app.get('/api/some/route', function(req, res) {
// some code...
}
}
Maybe this is not the best approach, but I have used it without problem in small apps.
This is how i do it
I have app/controllers/index which call register method each of the controller. Each controller has a register method that register its route with the app.
In controllers:
exports.register = function(app) {
app.post('/login', login)
}
In controllers index.js or routes or whatever you want to name it.
require('../controllers/auth').register(app)
require('../controllers/registration').register(app)
and at the end, drops all other routes to 404.
Related
I have gone through express document in that i have learn about
Router() and express.Router(). so my question is i have separated
my all routes from main app and created different folder there i did
not create any router object(var router express.Router()) for
routing to specific path still it's working fine. So i want to know
why this Router class is necessary ?
see, This is main app file,
'use strict'; const startUpDebugger=require('debug')('app:startUp');
const dbDebugger=require('debug')('app:db'); const express =
require('express'); const app = express(); const
moragan=require('morgan'); const helmet=require('helmet'); const
config=require('config'); const courses=require('./routes/courses');
const home=require('./routes/home'); app.use(helmet());
app.set('view engine','pug'); app.set('views','./view');
app.use(express.json()); app.use('/api/courses',courses);
app.use('/',home);
console.log(Node enironment variable: ${process.env.NODE_ENV});
console.log(Application name : ${config.get('name')});
console.log(mail server : ${config.get('mail.host')});
if(app.get('env')==='development'){
app.use(moragan('tiny'));
startUpDebugger("******Morgan enabled*******") }
const port = process.env.PORT || 5000; app.listen(port);
console.log(Api Node running on port ${port});
This is my courses.js which is my route file
const express=require('express'); const app=express
const courses=[{"id":1,"course":"course1"},
{"id":2,"course":"course2"},
{"id":3,"course":"course3"},
{"id":4,"course":"course4"}]
app.route('/posting').post((req,res)=>{
console.log(req.body);
courses.push(req.body)
res.status(201).send(courses); }).put((req,res)=>{
res.send("Successfully put message") }) app.get('/sub/:id',(req,res)=>{
res.status(200).send(req.params); })
module.exports=app;
your question is not clear but if i am getting you right:-
If your app is really simple, you don't need routers.
//you can just invoke express constructor and use it
const app=express()
app.get('/', function (req, res) {
res.send('root')
}) // app.get,app.post and so on
in your main app file.
But as soon as it starts growing, you'll want to separate it into smaller "mini-apps", so that it's easier to test and maintain, and to add stuff to it. You'll avoid a huge main app file :) .
so here you need to make another file for routes and have to invoke express.Router() class and use it
like:
//route.js
const Router=express.Router()
// middleware that is specific to this router
router.use(function timeLog (req, res, next) {
console.log('Time: ', Date.now())
next()
})
// define the home page route
router.get('/', function (req, res) {
res.send('Birds home page')
})
// define the about route
router.get('/about', function (req, res) {
res.send('About birds')
})
And import this file into the main app file and pass it to middleware to use
app.use('/',require('./routes/routes.js'))
and comparing to express() object the express.Router() object is light weight
I have a Node/Express application, and I need to move one route to a different file.
This is my index.js.
'use strict';
let express = require('express'),
bodyParser = require('body-parser'),
logger = require('morgan'),
_ = require('lodash');
let app = express();
app.use(logger('combined'));
app.use(express.static('public'));
app.use(bodyParser.json({}));
app.use(bodyParser.urlencoded({ extended: true }));
console.log("I am open");
let users = [///stuff ];
let games = [];
// Handle POST to create a user session
app.post('/v1/session', function(req, res) {
// do things
});
// Handle POST to create a new user account
app.post('/v1/user', function(req, res) {
// do things
});
// Handle GET to fetch user information
app.get('/v1/user/:username', function(req, res) {
// do things
});
// Handle POST to create a new game
app.post('/v1/game', function(req, res) {
// do things
});
// Handle GET to fetch game information
app.get('/v1/game/:id', function(req, res) {
// do things
});
let server = app.listen(8080, function () {
console.log('Example app listening on ' + server.address().port);
});
I want to have a new server side route (GET /v1/game/shuffle?jokers=false), but I don't quite understand how to separate it into a new file, perhaps in ./routes/shuffleRoute.js.
I read through this one, but I don't quite understand it due to the file names being similar. How to separate routes on Node.js and Express 4?
And I'm just trying to separate one route, not all.
Create a file in routes, called shuffleRoute.js. In this file write something like
var express = require('express');
var router = express.Router();
router.get("/shuffle", function (req, res, next) {
// magic here
});
router.get("/:id", function (req, res, next) {
// more magic here
});
module.exports = router;
and in your server.js
app.get("/v1/games", require("./routes/shuffleRoute.js"));
It's important to node that in your case, as you are using a param for id, your shuffle route needs to come before the :id route. Otherwise express will interpret shuffle as an id (which will hopefully not be an id)
If you only want to "outsource" "/v1/games/shuffle, make sure that comes before app.get("/v1/games/:id"...) in your server.js file
An endpoint works fine if added directly to my server.js file:
app.post('/test', function(req,res) {
res.status(200).send({"message" : "OK"});
});
but in an attempt to refactor the app I include a file called api.js from server.js like this:
var routesApi = require('./server/routes/api');
app.use('/v1', routesApi);
and it looks like this:
var express = require('express');
var router = express.Router();
module.exports = function() {
router.post('/test', function(req, res){
res.status(200).send({"message" : "OK"});
});
return router;
}
but if I try and hit this end point the req "stalls" as there is no response. What am I doing wrong?
Because of the way you exported your router, you need to invoke routesApi when adding it to the middleware stack via .use(). This is how that might look like
app.use('/v1', routesApi());
Though you can avoid this altogether by changing your api.js to look like this:
var express = require('express');
var router = express.Router();
router.post('/test', function(req, res){
res.status(200).send({"message" : "OK"});
});
module.exports = router;
and the code for the server can stay the same since now, you're exporting an instance of the Router module.
you have define global variable for app and may use like this:
api.js
exports.allRoutes=function() {
var version1="v1";
app.post('/'+version1+'/test', function(req, res){
res.status(200).send({"message" : "OK"});
});
}
app.js
global.app = express();
var all_routes = require('./server/routes/api');
all_routes.allRoutes();
var server = http.createServer(app);
server.listen(app.get('port'), function(req,res){
console.log('Express server listening on port ' + app.get('port'));
});
I was wondering how do I move all of my api routes in express into a separate routes.js file from my server.js file
I have a long list of api routes using app.use() for each route. So each route is in its own file, e.g. movies.js, movie.js but when I list these it makes for a long list in server.js
So I want to remove the list of api endpoints section from the below server.js out to a routes.js file.
Here is what I have currently:
server.js
import path from 'path'
import express from 'express'
import webpack from 'webpack'
import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackConfig from './webpack.config.dev'
const app = express();
/* api endpoints, can be many more, I want them in routes.js */
app.use('/api/movies', require('./src/api/routes/movies'))
app.use('/api/movie', require('./src/api/routes/movie'))
app.use(webpackDevMiddleware(webpack(webpackConfig), {
publicPath: webpackConfig.output.publicPath
}));
app.use('/public', express.static(__dirname + '/public'))
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.listen(3000, 'localhost', function (err) {
if (err) {
console.log(err);
return;
}
})
An example route
movies.js
var express = require('express');
var request = require("request");
var router = express.Router();
router.get('/', function(req, res) {
res.json({})
});
module.exports = router;
You can try to use the following modular approach.
Define controller files having logic per feature. e.g. movie.
movieController.js
module.exports = {
getMovie : function(req, res){
//do something
},
getMovies : function(req, res){
//do something
},
postMovie : function(req, res){
//do something
}
}
Then, reference that controller in routes files and simply plug those functions.
routes.js
var express = require('express');
var movieCtrl = require('./movieController');
var router = express.Router();
router.route('/movie').get(movieCtrl.getMovie);
router.route('/movie').post(movieCtrl.postMovie);
router.route('/movies').get(movieCtrl.getMovies);
module.exports = router;
And, in app.js, mount the routes to suitable location, e.g. /api
app.js
var routes = require('./routes');
app.use('/api', routes);
What I am trying to achieve is my statics being loaded on / , with the api mounted at /api
Here is my main file:
var express = require('express');
var server = express();
var app = require('./api/app');
server.use(express.static('/', __dirname + '/public'));
server.use('/api', app(server));
server.listen(3000);
My app.js file:
module.exports = function(app) {
app.get('/users/:id', function(req, res, next){
res.json(req.params);
});
}
I am getting a Cannot read property 'handle' of undefined error. I still haven't quite got my head around express' use and i'm sure im making a very novice mistake but just not sure how I can configure to get the result I would like.
Thanks.
You should use a Router instead with Express 4.x:
// main.js
var express = require('express');
var server = express();
var api = require('./api/app');
server.use(express.static('/', __dirname + '/public'));
server.use('/api', api());
server.listen(3000);
// ./api/app.js
var router = require('express').Router();
module.exports = function() {
router.get('/users/:id', function(req, res, next){
res.json(req.params);
});
return router;
};
use expects to receive a middleware function, but in this example it's not actually getting anything (notice that there's no return value in app.js). One way to fix this would be to return an instance of express' Router middleware:
var express = require('express');
module.exports = function(app) {
var apiRouter = express.Router();
apiRouter.get('/users/:id', function(req, res, next){
res.json(req.params);
});
return apiRouter;
};