I'm starting now with NodeJS and I'm having a problem accessing some functions in controllers with express.
Example:
My server.js:
var express = require('express');
var consign = require('consign');
var bodyParser = require('body-parser');
var expressValidator = require('express-validator');
var Recaptcha = require('express-recaptcha');
var recaptcha = new Recaptcha('blablabla', 'blablabla');
var app = express();
app.set('view engine', 'ejs');
app.set('views', 'app/views');
app.use(express.static('./app/public'));
consign()
.include('./app/routes')
.then('./app/models')
.then('./app/controllers')
.into(app);
module.exports = app;
app.listen(3000, function () {
console.log('Server ON');
});
My app/routes/home.js route:
module.exports = function (myapp) {
myapp.get('/site', recaptcha.middleware.render, function (req, res) {
myapp.app.controllers.home.pagina(myapp, req, res, {title: 'Cadastre-se', url: req.originalUrl, captcha: res.recaptcha});
});
};
My app/controllers/home.js controller:
module.exports.pagina = function (myapp, req, res, page) {
res.render("index", page);
};
You are returning the error:
ReferenceError: recaptcha is not defined at Function.module.exports (/Users/User/NodeJS_projects/myapp/app/routes/home.js:2)
If I call the middleware in the server.js file as follows:
...ss.static('./app/public'));
app.use(recaptcha());
consign()...
Returns the following error:
TypeError: recaptcha is not a function
How to solve this problem? Or, what would be the correct way to pass a middleware to controllers or routes?
There are a couple of issues. One, if you look at the documentation for the express-recaptcha module here, you need to parse the request body for this module to work. To do this you need the body-parser module, which you correctly have, but you also need to add the middleware:
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
You can add this right after defining app in your server.js file. Then, you do not have recaptcha defined in your home.js file. You can move the following definition from server.js to home.js:
var Recaptcha = require('express-recaptcha');
var recaptcha = new Recaptcha('blablabla', 'blablabla');
Also, you added app.use(recaptcha()); to your server.js file. recaptcha is not a function itself. It contains two middleware functions, one for rendering the widget (recaptcha.middleware.render) and the other for verifying the response from the widget (recaptcha.middleware.verify). These should be added to specific routes that are in charge of rendering and verification. I think if you look at the link I provided, it will be helpful.
Related
When I use the "use" method my code works fine, but when I use the "get" it gives an error: "Cannot GET /route1".
My Code:
const express = require('express');
const app = express();
const expbs = require('express-handlebars');
const path = require('path');
const routes = require('./routes/handlers');
app.use(express.static('public'));
const hbs = expbs.create({
defaultLayout: 'main',
layoutsDir: path.join(__dirname, 'views/mainLayout'),
partialsDir: path.join(__dirname, 'views/pieces'),
});
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');
app.get('/route1', routes);
app.listen(8080, () => {
console.log('Server is starting at port ', 8080);
});
I am new to node js, please tell me can i define routes with "get" method.
I believe your routes/handlers.js look something like this
var express = require('express');
var router = express.Router();
function greetUser(req, res){
res.send("Welcome dear user");
}
router.get("/", greetUser);
router.post("/", (req, res)=>{ res.send("user registered") });
module.exports = router
The problem here is this last line, this router object which is being exported works fine for app.use middleware, while .get or .post expects 2nd parameter to be a function
If you export this greetUser function from your router as well or receive this function from anywhere, this should start functioning well. Practically it would be
app.get("/route1", (req, res)=>{ res.send({status : true, message : "sample JSON"})})
If you are using router you coudn't use get method.
Here is the docs.
Only the handler has access to get method. app.use will add path to api route which point to get,post and etc.
You could only explicitly define a get as a standalone get route.
app.get('/route1', (req, res) => {
res.send("You have hit route1 - get");
});
When using router you could only include the router object as a parameter in app.use(path, routerObj) method.
app.get('/route1', routes);
woulde be app.use('/route1', routes);
I've recently completed a Node.js website locally, which works fine, though I have noticed some issues when uploading the website online to OVH Cloud Web Hosting. All pages, even those that should not exist, return the contents of the homepage.
I'm running Express with Node.js, and the file structure was created with express-generator. My app.js file contains the following:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var expressHbs = require('express-handlebars');
var Handlebars = require('handlebars');
var HandlebarsIntl = require('handlebars-intl');
var mongoose = require('mongoose');
var indexRouter = require('./routes/index');
var blogRouter = require('./routes/blog');
var blogItemRouter = require('./routes/blog-item');
var portfolioRouter = require('./routes/portfolio');
var contactRouter = require('./routes/contact');
var iBlogPostsRouter = require('./routes/i/blog-posts');
var iContactRouter = require('./routes/i/contact');
var iPortfolioItemsRouter = require('./routes/i/portfolio-items');
var portfolioItemRouter = require('./routes/portfolio-item');
HandlebarsIntl.registerWith(Handlebars);
var app = express();
// view engine setup
app.engine('.hbs', expressHbs({defaultLayout: 'layout', extname: '.hbs'}));
app.set('view engine', '.hbs');
app.disable('etag');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/blog', blogRouter);
app.use('/blog/:title', blogItemRouter);
app.use('/portfolio', portfolioRouter);
app.use('/contact', contactRouter);
app.use('/i/blog-posts', iBlogPostsRouter);
app.use('/i/contact', iContactRouter);
app.use('/i/portfolio-items', iPortfolioItemsRouter);
app.use('/portfolio/:title', portfolioItemRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {title: err.status + ' ' + err.message});
});
module.exports = app;
All of the routers have the same code, except render a different template. Here is an example of the indexRouter:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'About', about: true });
});
module.exports = router;
The issue is that every page, even my .js and .css files, returns the HTML from whatever is in the app.use('/' ...) router. The console returns the following error:
Resource interpreted as Stylesheet but transferred with MIME type text/html: "https://xxx.co.uk/core/styles/m.css".
I experimented with this by changing the homepage to be my contact page, which has resulted in every URL returning the contact page. My CSS and JavaScript are in a public folder. The only thing that I can think of is that the '/' route is somehow being used for every single request, but it doesn't make any sense to me why this could be happening.
Instead of using app.use('/<route>', <router>) in your project, try replacing it with the corresponding express statements, e.g,
router.<route_method>('/<route>', function(req, res, next){
// code
});
See if it works fine or not.
The reason your site is defaulting to the '/' route is because you haven't properly set up your routes. Each router module needs to know what is getting exported. Your indexRouter file, for example, needs to look like this:
var express = require('express');
var router = express.Router;
router.get('/', function(req, res){
res.render('index', { title: 'About', about: true });
});
module.exports = router; <<----
In addition, if the app.js you're showing as of 09/04/2018 06:36 is the complete app.js, you're missing a lot. You have a minimized CSS as your first stylesheet, which actually contains the rendered index.html.
I am actually not able to figure it out that why in index.js file in below code snippet is throwing me an error : app.get is not a function.
Please help me out..
//here is my app.js file
const express = require('express');
const app = express();
const helpers = require('./helpers');
const routes = require('./index')
app.use((req, res, next) => {
app.locals.h = helpers;
next();
});
app.use('/', routes);
app.set('views',(__dirname));
app.set('view engine', 'pug');
app.listen(3000,()=>console.log('port 3000'));
module.exports = app;
//here is my index.js file
const app = require('./app')
app.get('/',(req,res) => {
res.render('template');
})
module.exports = router;
//helpers.js
exports.title = "NODEjs";
//template.pug
doctype html
html
head
title=`${h.title}`
body
h1 myHeading #{h.title}
You have a circular dependency loop and rather than create an infinite loop, the require() subsystem detects that and fails to load your module.
In app.js, you load index.js. In index.js, you load app.js. Circular dependency loop.
There are two separate techniques that can be used to solve your particular problem. You appear to be using about some of one technique and some of another and that creates your problem.
A classic way to define new routes in a separate file is to just have that file create and export its own router. It then assigns the routes to the router (not to app) and thus that other file never needs the app object at all. Because you show module.exports = router, it appears you have part of that technique, but only part of it.
Here's how the code would work to do it that way:
// app.js
const express = require('express');
const app = express();
const helpers = require('./helpers');
app.use((req, res, next) => {
app.locals.h = helpers;
next();
});
// hook in routes from the index.js router
app.use('/', require('./index'));
app.set('views',(__dirname));
app.set('view engine', 'pug');
app.listen(3000,()=>console.log('port 3000'));
// index.js
const router = require('express').Router();
router.get('/',(req,res) => {
res.render('template');
});
module.exports = router;
You could also pass app to index.js when you load it rather than having it try to import app. This also solves the circular dependency issue.
const express = require('express');
const app = express();
const helpers = require('./helpers');
// pass app here so it can register routes
require('./index')(app);
app.use((req, res, next) => {
app.locals.h = helpers;
next();
});
app.use('/', routes);
app.set('views',(__dirname));
app.set('view engine', 'pug');
app.listen(3000,()=>console.log('port 3000'));
Change index.js to export a module constructor which you call and pass app to:
module.exports = function(app) {
app.get('/',(req,res) => {
res.render('template');
})
}
Add parenthesis on the first line :
const express = require('express')();
The first answer should be accepted.
This is happening only due to the circular dependencies in this case.
I have an express4 router that is skipping the base route and going directly to a designated ./user route. But I can not see why it is skipping the base route.
APP.js
var express = require('express');
var path = require('path');
var logger = require('morgan');
var bodyParser = require('body-parser');
var router = express.Router();
var app = express();
require('./routes')(app);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
//app.use('/', router);
module.exports = app;
./routes/index.js
var express = require('express');
var router = express.Router();
// route middleware that will happen on every request
router.use(function(req, res, next) {
// log each request to the console
console.log(req.method, req.url);
// continue doing what we were doing and go to the route
next();
});
/* GET home page. */
router.get('/', function(req, res) {
console.log('inside the root route');
});
//module.exports = router;
module.exports = function(app) {
// here we list our individual sets of routes to use in the router
require('./route/user')(app);
};
When I run the app (npm start), console displays the log that resides inside the user route and totally skips the base route ('/').
Where did I go wrong??
It appears that you are only exporting the user routes.
To make this a bit clearer, app.js only has access to the following when you require routes.index.js:
function(app) {
// here we list our individual sets of routes to use in the router
require('./route/user')(app);
};
hence why it is skipping the base route entirely.
Following the API documentation (under the 'express.Router' section), the correct code to export the routes would be:
// exports the router.use and router.get('/) routes
module.exports = router
Which would mean you'd have to include the user routes in another section (such as app.js).
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;
};