Using Route of express node.js but express.Router getting as undefined - javascript

My code of router from default routes/index
/* GET home page. */
exports.index = function(req, res){
res.render('user', { title: 'Abcd' });
};
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', { title: 'Express' });
});
router.get('/helloworld', function(req, res) {
res.render('helloworld', { title: 'Hello, World!' })
});
module.exports = router;
getting error as can not call method get of undefined.I am new in node js please anyone help me.

Try upgrading to Express 4.x. You are probably running a 3.x flavor.

Router is a middleware of express which is registered implicitly with the express object the first time post() or get() is used. You can but don't have to add this explicitly calling use(), which allows you to register various middleware with express and so allows configuring processing and behavior in consideration of precedence.
Correct initialization and usage might look like this:
EDIT: Changed the example to be a "complete" http server.
app.js
var http = require('http');
var express = require('express');
// Requiring express exports a function that creates the application. Call it!
var app = express();
// Set port to listen to
app.set('port', process.env.PORT || 3000);
// Set view engine
app.set('view engine', 'jade');
// Tell express to use the router middleware
// Can be omitted if precedence doesn't matter
// (e.g. for loading static resources)
app.use(app.router);
// Add callback handler for home (/) route
app.get('/', function(req, res) {
res.render('index', { title: 'Express' });
});
// Create http server by passing "app" to it:
http.createServer(app).listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
Now, if you place a minimal view into the default folder for views...
views/index.jade
doctype 5
html
head
meta(charset='utf-8')
title #{title}
meta(name='viewport', content='width=device-width, initial-scale=1.0')
body
div
h1 Gotcha! Title is "#{title}"
... and start your server from the console with...
$ node app.js
...you should have your first node/express/jade powered app up and running!

Related

Express.js Routing is not making sense

I'm working on an Express.js app and I think I am having trouble understanding the nuances of multi-layer routing. My app has the following segment of code in its app.js file:
//app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
//new stuff
const routes = require('./routes');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// middleware functions required
app.use(logger('dev')); //handles logging
app.use(express.json()); //JSON payload parser
app.use(express.urlencoded({ extended: false })); //urlencoded payload parser
app.use(cookieParser());
//content routes
app.use('/jquery', express.static(__dirname + '/node_modules/jquery/dist/'));
app.use('/', express.static(path.join(__dirname, 'public'))); //static files (css and other js files)
app.use('/', routes); //everything else (see /routes/index.js)
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
.
.
.
As indicated in the code, after a bunch of static file and default middleware setup for logging and such, app.use('/', routes); is declared, handing off to an index.js file in the /routes folder as follows:
//index.js
//main router entry point, sets up all route modules
//instantiate the express.Router class
const express = require('express');
const router = express.Router();
//import our route modules
const indexRouter = require('./indexRouter');
const resetRouter = require('./resetRouter');
const enrollRouter = require('./enrollRouter');
//map individual route modules to their respective routes
router.use('/', indexRouter);
router.use('/reset', resetRouter);
router.use('/enroll(/*)?', enrollRouter);
module.exports = router;
The three router.use lines call individual route files in the same directory as shown. The first two are simple get routes. The third one (router.use('/enroll(/*)?', enrollRouter);) has both get and post components via the enrollRouter.js file as follows:
//enrollRouter.js
const express = require('express');
const router = express.Router();
const { getEnroller } = require('../controllers/enrollGetController');
const { postEnrollment } = require('../controllers/enrollPostController');
router.post(/^(\/enroll\/new)/i, postEnrollment);
//router.post('/', postEnrollment);
router.get('/', getEnroller);
module.exports = router;
Here's where things get interesting. I'm using postman to make a post request to "/route/new". If the route string for the post route in the code above is set to '/', everything works fine, and enrollPostController.js is called returning appropriate content. However, if I set the route string to '/enroll/new' instead (the path I'm calling... doesn't matter if it's a string or a regex), the 404 error code in app.js is called.
I'm not following what is going on. I'm under the impression that the string at the beginning of a router.get or router.post call represents the path to be matched for the callback defined as the next parameter. When the path is clearly the one specified, why am I getting a 404?
The way I'm thinking, when the /enroll/new post request comes in, app.js should hand off to index.js for all routes matching '/'. Then index.js should hand off to enrollRouter because the route matches '/enroll(/*)?'. And then finally, enrollRouter.js should call postEnrollment defined over in ../controllers/enrollPostController, because the route matches '/enroll/new'. But it doesn't work that way.
Can someone enlighten? or fill in the holes in my understanding?
Here's the code in enrollPostController.js
//enrollPostController.js
module.exports = {
postEnrollment(erq, res) {
//at this point we have the form submission data.
console.log(erq.body);
res.send("received form submission!");
},
};
Try the following:
routes/index.js
// Delegate "/enroll/*" to router
router.use('/enroll', enrollRouter);
routes/enrollRouter.js
// Handle POST requests to "/enroll/new"
router.post('/new', postEnrollment);
I hope this helps.
If you are following some pattern and only endpoints are getting changed for example
http://localhost:4000/mycode/testUrl/abc
http://localhost:4000/mycode/testUrl/Pqr/xyz
http://localhost:4000/mycode/testUrl/abc/xyz/pqs
const service = express.Router();
// **console** is just to check your endUrl. you can print originalUrl as well
service.get('/*', function(req, res) {console.log(req.url); }
service.post('/*', function(req, res) { console.log(req.url);}
app.use('/mycode/testUrl', service);
In your index.js
The express router defined as
router.use('/enroll(/*)?', enrollRouter);
passes the '/enroll/new' to your enrollRouter.js
so all you need to give the "/" in the post route, so the "/enroll/new" is right in front of it but due to nesting of routes we can separate them.
Hope I answered the question.

Error: Module "html" does not provide a view engine (Express)

I'm trying to set up a simple routing app but I keep running int the error when rendering a page.
Error: Module "html" does not provide a view engine.
What is odd is I've specified the view engine in my app.js file but I'm still getting the error
// app.js
var express = require('express');
var app = express();
var router = express.Router();
// Need to import the route file
var chef = require('./chef');
app.use('/chef', chef);
// Set directory to contain the templates ('views')
app.set('views', __dirname + '/views');
// Set view engine to use
app.set('view engine', 'html');
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
// chef.js
var express = require('express');
var routes = express.Router();
routes.get('/', (req, res) => {
//res.send("I'm here!")
res.render('chef');
});
module.exports = routes;
// views/chef.html
Some HTML file here here ..
In the chef.js file when I just want to test if the route is working I uncomment res.send ... which sends "I'm here" to the DOM.
However whenever I try res.render to render the chef.html page I get the error above. Which I find odd because I've set the view engine in app.js.
Suggestions on how to render my HTML file?
use res.sendFile('/fileName.html'); instead of res.render()
for sending file , we used res.sendFile(fullPath) and if you are using other than HTML language then you should have to use res.render().
res.render() for template like ejs, pug etc.

Express not working as expected

I am trying to set up a react app with express running. However, I can't understand why it won't load the page I want it to
this is my app.js:
var express = require('express');
var app = express();
app.use('/', express.static('public'));
app.get('/', function(req, res) {
res.sendfile('./index.html');
});
app.get('/canYouPlay.js', function(req, res) {
res.sendfile('/canYouPlay.html');
});
app.listen(process.env.PORT || 8080);
This works. however if I change the first app.get to:
app.get('/', function(req, res) {
res.sendfile('./canYouPLay.html');
});
It still renders the same HTML file even when restarting the app even though they are different files.
also when i run this function:
handleClick: function() {
document.location.replace('./canYouPlay');
},
it says it cannot get /canYouPLay even though a HTML and js file exist with that name.
what have I missed or doing wrong?

Why am I getting "name undefined" when trying to post using Express and Body Parser

I'm attempting to build a MEAN app and trying to test POSTing with POSTMAN. When I do, I keep getting the dreaded "TypeError: Cannot read property 'name' of undefined". If I type in a simple string, the POST goes through fine. But when I use "req.body.name" I get the error. I've looked in every place and I'm not seeing my mistake. I even followed the suggestions on this thread with no luck. Any help or suggestions would be greatly appreciated.
Here's the code I am currently working with in my server.js file:
const express = require('express');
var bodyParser = require('body-parser');
var Bear = require('./models/bear')
var path = require('path');
var mongoose = require('mongoose');
var router = express.Router();
var app = express();
var staticAssets = __dirname + '/public';
app.use(express.static(staticAssets));
app.use('/api', router)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
// Routes for my API
//===================================
// middleware to use for all requests
router.use(function(req,res,next){
// logging happens here
console.log('Something will happen.');
next(); // Head to the next router...don't stop here
});
// Test router to make sure everything is working (accessed at GET http://localhost:3000/api)
router.get('/', function(req, res){
res.json({message: 'hooray! welcome to our api!'})
})
//More routes will happen here with routes that end in "/bears"
router.route('/bears')
//Create a bear (accessed at POST http://localhost:3000/api/bears)
.post(function(req,res){
var bear = new Bear(); // Create a new instance of the bear model
console.log(req);
bear.name = req.body.name; // set the bears name (comes from the request)
//res.send(200, req.body);
bear.save(function(err){
if (err)
res.send(err);
res.json({message: 'Bear Created!!'});
});
});
//======================================
//var Products = require('./products.model.js');
var Product = require('./models/product.model');
var db = 'mongodb://localhost/27017';
mongoose.connect(db);
var server = app.listen(3000);
console.log("App is listening on port 3000");
Thanks.
Also, the url I'm trying to use inside of POSTMAN is http://localhost:3000/api/bears
Express processes requests Top-Down, meaning if you require a piece of functionality to be applied to all routes via middleware, than that middleware needs to be added to your app before any routes that require it. This is usually the case for middleware such as body-parser.
When using Router Middleware, you don't typically construct the router in the same file as the actual Express app that will use it as middleware. Instead, place it in a separate file and/or directory for organization purposes, this is considered a best practice.
Express Apps can be structured like so
/lib
/models
bear.js
product.js
/node_modules
/public
/css
/routes
api.js
package.json
server.js
The routes directory is where you would place any applicable Router Middleware files such as your api router. server.js is your main Express App and public is where your static assets are stored. lib is directory that contains any business logic files and models.
The actual Express app and Router files should look something like this
server.js
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const apiRouter = require('./routes/api');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, public)));
app.use(/api, apiRouter);
app.listen(port, () => {
console.log(`Listening on port ${port});
});
module.exports = app;
routes/api.js
'use strict';
const router = require('express').Router();
const Bear = require('./lib/models/bear');
router.use((req, res, next) => {
// logging happens here
console.log('Something will happen.');
next(); // Head to the next router...don't stop here
});
router.get('/', (req, res) => {
return res.json({ message: 'hooray! welcome to our api!'})
});
router.route('/bears')
//Create a bear (accessed at POST http://localhost:3000/api/bears)
.post((req, res) => {
var bear = new Bear(); // Create a new instance of the bear model
console.log(req);
bear.name = req.body.name; // set the bears name (comes from the request)
//res.send(200, req.body);
bear.save((err) => {
if (err)
return res.send(err);
return res.json({message: 'Bear Created!!'});
});
});
module.exports = router;
To note, you could break up your API even further to increase the amount of decoupling. An example of this would be to move the /api/bear route to its own router middleware and into its own route file. Then simply add it to your routes/api.js router as a middleware like you would in server.js. If your app is going to have a decent sized API, then this would be the best approach because it would allow the most flexibility when it comes to applying middleware to only certain routes and would make maintaining the source much easier.

How to mount app.get() routes on a particular path prefix

I'm writing an API using Node.js and Express. My API has GET methods of the form:
/api/v1/doSomething
/api/v1/doSomethingElse
My code is looking something like this:
server.js:
var app = express();
...
var routes = require('./routes')
routes.attachHandlers(app, '/api/v1')
routes/index.js
...
module.exports.attachHandlers = function(app, context) {
//get a list of all the other .js files in routes
//for each route, require() it and call it myRoute
myRoute.attachHandlers(app, context)
}
routes/some-route.js
...
module.exports.attachHandlers = function(app, context) {
app.get(context + '/doSomething', doSomething)
app.get(context + '/doSomethingElse', doSomethingElse)
}
...
Effectively I'm passing the context path/mount point down through the app. If somebody were to write a route like the following, though, the context would be lost:
app.get('/doFoo', foo)
Rather than having that part of the API mounted on /api/v1/doFoo it's on /doFoo. I would like to avoid having to pass the context path around like this.
app.use supports mounting middleware on an optional mount path. I have seen references online to mounting an entire Express application on a mount path using app.use. This seems like the sort of thing I want to do, but I'm not sure how to do it or if it's the best solution for my particular use case.
To summarise - I want to mount my app.get() routes with a particular prefix by default. What's the best way of doing this?
With Express 4.0, the task is much cleaner with the Router. You can create as many routers as you need to nicely partition your app, and then attached them with app.use(). For example:
myapp.js
var express = require("express"),
router = express.Router(),
app = express(),
port = 4000;
// Here we declare our API which will be visible under prefix path
router.get('/', function (req, res) {
console.log("request to subspace hello");
res.send({ message: "Hi from subspace /api/v1/"});
});
// we attach our routes under /api/v1
app.use('/api/v1', router);
// here we have direct, root-level routing
app.get('/', function (req, res) {
console.log("request to rootspace hello");
res.send({message: "Hi from root /"});
});
app.listen(port);
console.log("App active on localhost:" + port);
Then run
node myapp.js
and visit
http://localhost:4000 and http://localhost:4000/api/v1
Here's a working example of mounting a route in Express 3:
./snipe3app.js
var express = require('express');
var app = module.exports = express();
app.get('/subapp', function (req, res) {
res.send('You are on the /sub/subapp page.');
});
./app.js
var express = require('express'),
http = require('http'),
subApp = require('./snipe3app'),
app = express();
app.use(express.favicon());
app.use(express.bodyParser());
app.use(app.router);
app.use('/sub', subApp);
app.get('/', function (req, res) {
res.send('You are on the root page');
});
http.createServer(app).listen(3000, function(){
console.log('Express server listening on port 3000. Point browser to route /secure');
});
You have to pay attention to the order in which the routes are handled when doing this.
I think express-namespace will work for this.

Categories