i am really new to Node Js and Express Js and i am following the (book)[http://www.sitepoint.com/store/jump-start-node-js/] to learn Node Js.
In the book the author created a simple page for simple Login Form. I am following that but getting 404 Not found.
Not Found
404
Error: Not Found
at Layer.app.use.res.render.message [as handle] (/Applications/MAMP/htdocs/resto/app.js:29:15)
at trim_prefix (/Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:240:15)
at /Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:208:9
at Function.proto.process_params (/Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:269:12)
at next (/Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:199:19)
at next (/Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:176:38)
at /Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:137:5
at /Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:250:10
at next (/Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:160:14)
at next (/Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:176:38)
I added the following code in App.js
var fs = require('fs');
app.get('/form', function(req, res){
fs.readFile('.views/form.html', function(error, content){
if(error){
res.writeHead(500);
res.end();
}
else{
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(content, 'utf-8');
}
});
});
and then created a file form.html in Views folder in which i created a simple html form.
This didnt work for me, so following the flow of default index.jade, i created a file form.js and added the following code in it
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/form', function(req, res) {
res.render('form');
});
module.exports = router;
Which also did not work. I am sure i am doing something wrong but i do not know where.
Please help, Thanks
Assuming you have those files :
-- app.js
-- routes (folder containing root.js)
-- views (folder containing form.jade)
Then, in your app.js :
var path = require('path');
var express = require('express');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use('/', require('./routes/root')); // Say that all the routes defined in root.js will start with http://yourdomain.com/
And in root.js :
var express = require('express');
var router = express.Router();
/* GET http://yourdomain.com/form */
router.get('/form', function(req, res) {
res.render('form'); // Render form.jade view
});
Of course, this is really minimalist and you'll have much more things to do... but I hope this will help you to better understand node.js using Express
Express Router documentation
I am new to NodeJS and Express too but I think the problem is that you never declare where to find the form.html file. Right before the app.get('/form',....), put app.use(express.static(__dirname+'put the directory your form.html is in or dont put anything if it's not in a directory')); this way express knows where to find the form.html and you shouldn't get a 404 anymore
Express provides a sendFile function in the response object, which allows you to do this:
app.get('/form', function(req, res){
res.sendFile('./views/form.html', {root: __dirname}, function(error, content){
if(error){
res.writeHead(500);
res.end();
}
});
});
The jade renderer isn't used in this case.
Related
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.
I am getting this error when I run npm start to run my express app.
TypeError: Router.use() requires middleware function but got a Object
my app.js code
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
/// catch 404 and forwarding to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
my index.js code
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', { title: 'Express' });
});
/* GET Hello World page. */
router.get('/helloworld', function(req, res) {
res.render('helloworld', { title: 'Hello, World!' })
});
module.exports = router;
I am quirte new to using Node and express. I cant see where I have gone wrong. Can anybody see what my problem is?
I found the answer in the comments from Kop4lyf:
check your users.js. It should also be exporting the router like
index.js, if you can try that.
However, this question was my top search result when I ran into this issue, so I am promoting to an answer.
The error is caused because one of your route modules is not being exported - meaning Express does not have access to it when it tries to identify all of your routes.
You can fix this by adding module.exports = router; to the end of each of your route files.
Example:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
//Do whatever...
});
module.exports = router;
More information about module.exports can be found on this question or the offcial Node.js documentation.
I have fixed this by adding which i am using somewhere. So please check your all exports.
module.exports = router;
If you use in routes
exports default router
Your solution can be
module.exports = router
I had the same error , fixed it by replacing app.use('view engine', 'ejs') with app.set('view engine', 'ejs').
For reference I used this webpage Migrating from 3.x to 4.x
I didn't have to make any changes to either index.js or application.js. For more information on EJS one could refer Using EJS with Express and Express 4.x API
Your index.js file is fine you just have to create users.js and export it.
let express = require('express');
let router = express.Router();
//Login Page - GET REQUEST
router.get('/login',(req,res)=> {
res.send('login page');
})
//Register Page - GET REQUEST
router.get('/register',(req,res)=> {
res.send('register page');
});
module.exports = router;
in every module **export the router** and **keep one handler for the default
path '/'**
// in index.js
const authRoute = require("./routes/authRoute");
app.use("/auth", authRoute);
// in authRoute.js
const express = require("express");
const router = express.Router();
router.get("/", (req, res) => {
// code
});
module.exports = router;
This error comes when you forgot to export the module which uses the Router.
Your mentioned code works perfectly with some tweaks.
if your app.js is main/starting point of the app.
it should have
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}...`));
instead of
module.exports = app;
(optional)Generally index.js is used for starting point of app. Rename index.js as helloworld.js and change same at require statement
var routes = require('./routes/index');
to
var routes = require('./routes/helloworld');
run this app using the following command
node app.js
If you have checked all the solution than also having this error than check this one
Another cause of having this error is calling a method which is not exist or not not exported.
In my case i am calling login method but i forgot to define them
I was trying to call this method
app.post('/api/login', db.login);
but i had forgot to create login method so i got this error. also try to check spelling mistake may be you might have typed wrong spell
I had the same problem, and then I discovered that I was missing this line in one of my controllers !
return api; //it might be return routerfor your code !
I added this line to my code and it worked fine.
Whew, my problem was that i was doing module.exports = { router } instead of module.exports = router
I found it after lot of struggle! as everything syntactically correct, nothing wrong with code that was written, it was due to the code that was not written yet! This could happen if you have implemented index.js but not yet users.js. However, you have already defined both lines
app.use('/', routes);
app.use('/users', users);
If you are eager to test index.js right away without waiting for users.js to be implemented. That's exactly when it errors out.
if you are still facing this problem and try every solution then just replace router with routes and it worked fine
For anybody using EJS:
In my case I was receiving this error as I used
app.use("view engine","ejs")
instead of
app.get("view engine","ejs")
I fixed it by removing the app.use(/users, users);
I don't need this at the minute so maybe that is why it started breaking.
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.
I'm not new to JavaScript but I am new to Node.js and back end languages. I have a very simple question.
I've installed and setup Node.js on my computer and I'm attempting to get a server going between my static files & directory(s) and my browser to be able to send and receive requests. I've downloaded Braintree's free Sandbox (found here) for practice to get some faux transactions going just to gain a better understanding of how this can work.
I set up a local server by running npm install -g http-server on my command line and then http-server to set it up.
I then received the following message in my command line:
Starting up http-server, serving ./public
Available on:
http://127.0.0.1:8080
http://10.0.1.4:8080
Hit CTRL-C to stop the server
So, with this setup...if I wanted to do get() and post() methods and see it rendered and communicating between my "server" and my static files. How do I do this? For example, if I were to set up Braintree's sandboxed environment and then create a clientToken using the following code from Braintree's website
const http = require('http'),
url = require('url'),
fs = require('fs'),
express = require('express'),
braintree = require('braintree');
const gateway = braintree.connect({
environment: braintree.Environment.Sandbox,
merchantId: "xxxxx",
publicKey: "xxxxx",
privateKey: "xxxxx" //blocked out real numbers for privacy
});
Here is the remaining code I hae to create a "client Token" for a transaction...and here is the guide I'm following via Braintree's website...
http.createServer((req,res) => {
gateway.clientToken.generate({
},(err, response) => {
if(err){
throw new Error(err);
}
if(response.success){
var clientToken = response.clientToken
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(clientToken);
res.end("<p>This is the end</p>");
} else {
res.writeHead(500, {'Content-Type': 'text/html'});
res.end('Whoops! Something went wrong.');
}
});
}).listen(8080,'127.0.0.1');
So, my question is...if I wanted to generate send a token to a client using the get() method...how would I do that? Would it have to be a separate js file? How would they be linked? If they're in the same directory will they just see each other?
Here is an example on Braintree's website of how a client token may be sent:
app.get("/client_token", function (req, res) {
gateway.clientToken.generate({}, function (err, response) {
res.send(response.clientToken);
});
});
How could this be integrated into my current code and actually work? I apologize if these are elementary questions, but I would like to gain a better understanding of this. Thanks a lot in advance!
I don't know much about braintree, but usually you would use somthing like express.js to handel stuff like this. So I'll give you some quick examples from an app I have.
#!/usr/bin/env node
var http = require('http');
var app = require('../server.js');
var models = require("../models");
models.sync(function () {
var server = http.createServer(app);
server.listen(4242, function(){
console.log(4242);
});
});
So that's the file that gets everything started. Don't worry about models, its just syncing the db.
var express = require('express');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var app = express();
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
// share public folder
app.use(express.static(path.join(__dirname, 'public')));
require('./router.js')(app);
module.exports = app;
next up is the server.js that ties eveything together. app.use() lines are for adding middleware and the app.use(logger('dev')); sets the route logger for what your looking for.
app.use(express.static(path.join(__dirname, 'public'))); shares out all files in the public directory and is what your looking for for static files
var path = require('path');
module.exports = function(app){
//catch
app.get('*', function(req, res){
res.sendFile(path.join(__dirname, '..', 'public', 'index.html'));
});
}
last piece is the router.js. This is were you would put all of you get and post routes. generally I've found that if you see app.get or app.post in examples there talking about express stuff. It's used a lot with node and just makes routing way easier.
Also if your using tokens a route would look like this.
app.get('/print', checkToken, function(req, res){
print.getPrinters(function(err, result){
response(err, result, req, res);
});
});
function checkToken(req, res, next){
models.Tokens.findOne({value: req.headers.token}, function(err, result){
if(err){
res.status(500).send(err);
}else if(result == null){
console.log(req.headers);
res.status(401).send('unauthorized');
}else{
next();
}
});
}
so any route you want to make sure had a token you would just pass that function into it. again models is for db
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.