I am building an Express app and having some issues with routing. My '/' route is working perfectly, however other routes are not. I've looked into other questions people have posted and these have not resolved my issues.
I have a routes/index.js file:
module.exports = function(app){
app.use('/', require('./routes/home'));
app.use('/about', require('./routes/about'));
}
My routes/home.js: - WORKING!
const express = require('express');
const router = express.Router();
router.get('/', function(req, res) {
res.render('app/home');
});
module.exports = router;
My routes/about.js: - NOT WORKING!
const express = require('express');
const router = express.Router();
router.get('/about', function(req, res) {
res.render('app/about');
});
module.exports = router;
When I go to '/about' I see this error in the browser - 'Cannot GET /about'
Both the home.html and about.html files are located in the same views directory.
Any help here would be very appreciated!
let me quote from express doc:
A route will match any path that follows its path immediately with a “/”. For example: app.use('/apple', ...) will match “/apple”, “/apple/images”, “/apple/images/news”, and so on.
see express doc
this is "not working" because you set the /about in the app.use and in the router.get. try to request /about/about and you will see that this is working (just not as you wanted to)..
now just change the /about in the routes/about.js then rerun and try to request /about and it will work :)
Your route is set to /about/about.
Change about.js to this:
const express = require('express');
const router = express.Router();
router.get('/', function(req, res) {
res.render('app/about');
});
module.exports = router;
Related
The normal get method works fine on my main server.js file. I also use server.get('/favicon.ico', (req, res) => res.status(204)); to tackle the issue of the favicon request. It works well, again only on my main server.js file.
When I try to separate the code, by creating a user.js file that handles the api calls, I get:
::ffff:127.0.0.1 - GET /favicon.ico HTTP/1.1 404 150 - 1.669 ms
::ffff:127.0.0.1 - GET /users HTTP/1.1 404 144 - 0.454 ms
This is my main file - server.js:
const express = require('express');
const morgan = require('morgan');
const server = express();
const router = require('../routes/user');
const mysql = require('mysql');
server.use(morgan('short'));
//server.use(express.static('../public'));
server.use(express.json());
server.use(express.urlencoded({ extended: false }));
router.use(router);
server.get('/', (req, res) => {
console.log("Test!");
res.send("This works!");
});
//server.get('/favicon.ico', (req, res) => res.status(204));
server.listen(3003, () => console.log('Program is running! Port: 3003'));
This is my user.js file:
const express = require('express');
const mysql = require('mysql');
const router = express.Router();
router.get('/users', (req, res) => {
res.send('Hello');
});
router.get('/favicon.ico', (req, res) => res.status(204));
module.exports = router;
I'm not sure if this is related but I also experience the same problem when trying to server.use(express.static('../public')). It doesn't work. I cannot serve my html file. I've tried using the csp headers when requesting but that doesn't work. Setting up a CSP policy in the html header meta tag is not working either.
These are the versions of certain modules and technologies if you see a problem in any of their versions:
Apache 2.4.39
Node 6.9.0
Windows 7 - Yeah I know but bear with me
If anyone can help with eigther the router issue or the static file server issue it would much appreciated.
Thank you.
A simple way to do this is, in your server.js file add
server.use("/user", require("./routes/routes"));
note: routes is a folder here and routes.js is a file inside that folder.
then in your route.js file add
const express = require('express');
const router = express.Router();
const user = require('../controllers/user.controller');
// register controllers
const userController = new user();
userController.register(router);
module.exports = router;
pass your router in the user register(router) method. and it will be easily accessible in your user.js file.
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 new to Node.js and express framework. I am getting an error when I am trying to go to the signuplogin route from my homepage route. I have also tried all the similar questions in the stackoveflow, but none of them have worked for me, so I thought of posting my own.
This is my app.js
var homepage = require('./routes/homepage');
var signupLogin = require('./routes/signuplogin');
var app = express();
app.use("/", homepage);
app.use("/signup-login", signupLogin);
This is my homepage.js in routes directory
var express = require('express');
var homepageRouter = express.Router();
/* GET Homepage. */
homepageRouter.get("/", function(req, res, next) {
res.render('../views/homepage/homepage.hbs');
});
module.exports = homepageRouter;
This is my signup-login.js in routes directory
var express = require('express');
var signupLoginRouter = express.Router();
/* GET Signup Login Page. */
signupLoginRouter.get("/signup-login", function(req, res, next) {
res.send('respond with a resource');
});
module.exports = signupLoginRouter;
Well my "/" route works perfectly but it says 404 when I try to access "/signup-login" route.
I also changed the route to "/signuplogin" because I thought maybe it doesn't except the "-" character in the route. But that didn't work as well. Any solution/advice?
You have done a mistake in your signup-login.js file. Correct the code with this -
/* GET Signup Login Page. */
signupLoginRouter.get("/", function(req, res, next) {
res.send('respond with a resource');
});
As per your code the actual url of signup page becomes to "/signup-login/signup-login"
You don't need to add the singup-login url path again in your page. That is already referenced in your main router.
I have been looking for solutions for a couple days now trying to google it and all and now i am here. I am trying to setup subdomains for my app using express-subdomain package. However in the example below the app ALWAYS returns app.get route and skips the other subdomain routes specified.
I have also in turn added the hosts file url so i know that should not be the issue.
It must be in my code for some reason it always ends up displaying Detect Region route even when accessing oce.localhost:3000.
Please help me :)
Server.js
var subdomain = require('express-subdomain');
var express = require('express');
var app = express();
// Region routes
var router = express.Router();
var na = require('./routes/region/na.js');
var oce = require('./routes/region/oce.js');
router.use(subdomain('na.localhost', na));
router.use(subdomain('oce.localhost', oce));
app.get('/', function(req, res) {
res.send('Detect Region and send to correct subdomain!');
});
app.listen(3000);
routes/region/oce.js
var
express = require('express'),
router = express.Router();
router.get('/', function(req, res) {
res.send('Your are in OCE Region!');
});
module.exports = router;
And na.js is pretty much the name as oce.js
Cheers
You are setting your subdomains in the router variable but you don't tell your app to use it.
You have to do that :
app.use(router);
You put it in place of your current app.get.
Edit
You could also put your app.get after the app.use(router) so that it will act as a default route. (When you are neither on oce or na, it will use it)
Edit after some testing
Alright I've been able to make it work using express-vhost. I just updated your server.js like so :
var subdomain = require('express-vhost');
var express = require('express');
var app = express();
// Region routes
var router = express.Router();
var na = require('./routes/region/na.js');
var oce = require('./routes/region/oce.js');
subdomain.register('na.localhost', na)
subdomain.register('oce.localhost', oce)
app.use(subdomain.vhost(app.enabled('trust proxy')));
app.get('/', function(req, res) {
res.send('Detect Region and send to correct subdomain!');
});
app.listen(3000);
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.