Each piece of this code works individually but when put together, the Article section (third set) will not load. I am fairly new to coding so I was hoping for someone to point me in the right direction. I assume this is because the first route is executed and it never hits the second route...but I don't know how to fix it.
// Adds "www." to all URLs
app.all('*', function(req, res, next) {
if (req.headers.host.match(/^www/) == null) {
res.redirect('http://www.' + req.headers.host + req.url);
} else {
next();
}
});
// Serves the .html file but displays without .html in the URL
app.get('*', function(req,res){
var pages = ['/now', '/home', '/itinerary','/exploreourroots','/contact','/credits'];
if (pages.indexOf(req.url.toLowerCase()) !== -1) {
res.sendFile(__dirname + '/public' + req.url + '.html');
};
});
// Loads Articles from the database on the home page
app.get('/home', function(req, res) {
var query = 'SELECT a.title,a.author,a.cover_photo,a.html_loc,a.date_published,c.name country_name FROM articles a INNER JOIN countries c ON c.id=a.country_id ORDER BY a.date_published desc;'
connection.query(query, function(err, rows, fields) {
var list = [];
for (var i = 0;i < rows.length; i++) {
list.push({html_loc: rows[i].html_loc,country_name: rows[i].country_name,cover_photo: rows[i].cover_photo,title: rows[i].title,author: toAuthorPhoto(rows[i].author),date_published: toArticleDate(rows[i].date_published)});
}
res.contentType('application/json');
res.send(list);
});
});
Thanks for the help!
I'm not sure what intentions you have.
What if user type in browser www.mydomain.com/home. You want to return static html file (home.html), which is done by second router. Or you want to serve then article from db (third route)?
If you want to serve article from db when url is /home, then replace order of second and third routes:
app.get('/home', function(req, res) { ... });
app.get('*', function(req,res){ ... });
if you want to serve static html when your route is /home and also you want to have possibility to serve articles, then as before replace orders and additionally change /home router to /article. Then you will serve articles if url is /article :
app.get('/article', function(req, res) { ... });
app.get('*', function(req,res){ ... });
Related
I have two separate app.get routes that render "/" and contain mongoose find{} methods, which relates to two mongodb collections. I then have corresponding post routes that redirect/post to "/" with the data I entered on the forms.
Depending on the form I use (devportals/new or writingportals/new) to submit my data, I would like it to use the correct app.get to find the data and then populate my index.ejs file to display the new entry.
When I submit my post, it always defaults to the devportal.find{} GET route at the top even though I submitted my update to mongodb through the writingportals form.
app.get("/", function (req, res){
devportal.find({}, function(err, newDevPortal){
if(err){
console.log(err);
}else{
res.render("index",{newDevPortal: newDevPortal});
}
});});
app.get("/", function (req, res){
writingportal.find({}, function(err, newWritingPortal){
if(err){
console.log(err);
}else{
res.render("index",{newWritingPortal: newWritingPortal});
}
});
});
app.get("/portals/writingportals/new", function(req, res){
res.render("portals/writingportals/new");
});
app.get("/portals/devportals/new", function(req, res){
res.render("portals/devportals/new");
});
app.post("/", function(req, res){
var wpTitle = req.body.writingtitle;
var wpUrl = req.body.writingurl;
var wpImageUrl = req.body.writingimageurl;
writingportal.create({title: wpTitle, url: wpUrl, imageurl: wpImageUrl}, function(err, newWritingPortal){
if(err){
console.log(err);
}else{
res.redirect("/");
}
});
});
app.post("/", function(req, res){
var devTitle = req.body.writingtitle;
var devUrl = req.body.writingurl;
var devImageUrl = req.body.writingimageurl;
devportal.create({title: devTitle, url: devUrl, imageurl: devImageUrl}, function(err, newDevPortal){
if(err){
console.log(err);
}else{
res.redirect("/");
}
});
});
I have two separate app.get routes that render "/"
Your endpoints do not render "/", they get triggered based on the request uri, which in your case is "/".
Next, you cannot have two endpoints with the same route and same type of request, this is true with any web server. So in your case, you have two endpoints defined for GET requests to '/'. There is no way for your code to understand the difference between those two routes, so it will always hit the first one it finds.
Finally I'll add that for your solution, you most definitely will want unique endpoints because you are taking a template with a data model and sending back markup.... basically an endpoint for each page.
I will say that I'm not a huge fan of that approach. I think it makes life easier using a framework like react, then have every request to '/' return index.html with a reference to your react code... instead of the whole SSR deal.
However, for a lot of things, its simple to just use query parameters in the request. Here is an example where one endpoint is defined that will return all data from any collection through query parameters:
app.get('/api/collection', function(req, res) {
var collection = req.query.collection;
var _collection = db.collection(collection);
_collection.find({}).toArray(function(err, docs) {
if (err)
return res.status(500).send(err);
res.send(docs);
})
})
And then the request url would be GET -> /api/collection?collection=NAME_OF_YOUR_COLLECTION
I want to redirect incoming request to different endpoints based on a query parameter in the request.
For example,
http://localhost:9000/?category=xyz¶m1=...¶m2=...
category value can be one of [abc, ijk, pqr, xyz].
Based on category value, request should get redirected to one of "/abc", "/ijk", "/pqr", "/xyz" preserving remaining parameters.
So, the above request should become /xyz/?param1=...¶m2=...
I am new to Nodejs/express, I thought it is better to create different routes based on category value to modularize the code.
What is the ideal approach to handle such cases?
Looks like the old "front page controller" pattern:
app.get('/', routeByParameter)
function routeByParameter(req, res){
var category = req.params.category
if(category === 'abc'){
return abcRoute(req, res)
}
else if(category === 'xyz'){
return xyzRoute(req, res)
}
}
function abcRoute(req, res){
req.send('abc')
}
OR to use the "front page terminology"
app.get('/', dispatcher)
function dispatcher(req, res){
var category = req.params.category
if(category === 'abc'){
return viewAbc(req, res)
}
else if(category === 'xyz'){
return viewXyz(req, res)
}
}
function viewAbc(req, res){
req.send('abc')
}
Alternatively, you could get in and modify or create a custom route dispatcher in the middleware...
Create one route for each of these values [abc, ijk, pqr, xyz]. For handling different query parameters (?category=xyz) create a middleware that transform the request url:
app.use(function(req, res, next) {
// adding category in the url path will redirect to the
// correct route after calling next function
req.url = "/" + req.query.category;
next();
});
Assuming it's a GET request the categories routes would be:
app.get('/abc', function(req, res) {
//do stuff for 'abc' category
res.send('abc');
});
app.get('/ijk', function(req, res) {
//do stuff for 'ijk' category
res.send('ijk');
});
app.get('/pqr', function(req, res) {
//do stuff for 'pqr' category
res.send('pqr');
});
app.get('/xyz', function(req, res) {
//do stuff for 'xyz' category
res.send('xyz');
});
Note that middleware will edit url for all requests, filter by the request url adding the path app.use("/path", function(req,res,next)... or add some logic inside it.
I had like 100 blogs on "/" page and also a link to Sortby Date:a-z When I click
these link I m transferred to different routes one is "/sort_by_date" and other is "/sort_alphabetically".I want this sorting to appear on "/".I m not able to do it on "/" page that is whay I had specified to different routes.I want this sorting to appear on "/" page by clicking to differnt links different sorting should be appear.This whole application is written in nodejs Mongoose express.
The homepage of the blog
router.get('/', function (req, res) {
var q= blog.find({}).limit(100);
q.exec(function(err,docs)
{
res.render('blog',{"no_of_blogs":docs
,"in_ca":true })
});
});
The page which is sorting by date
router.get('/sort_by_date', function (req, res) {
blog.find({},{sort:{date:-1}},function (err, docs) {
res.render('index_date_blog',{"no_of_blogs":docs
,"in_ca":true })
});
});
This is the page sorted by alphabetically
router.get('/sort_alphabetically', function (req, res) {
blog.find({},{sort:{title}},function (err, docs) {
res.render('index_date_blog',{"no_of_blogs":docs
,"in_ca":true })
});
});
Thanks in advance.
Use the query string to pass in the sort variable.
Make your links to change the sort link to ?sort=title or ?sort=date
Note, below code is not tested, but should help you along the way:
router.get('/', function (req, res) {
var sortQuery = req.query.sort;
var sort = {};
if(sortQuery=='date')
sort={date:-1}
if(sortQuery=='title')
sort={title: 1}
var q= blog.find({}).limit(100).sort(sort);
q.exec(function(err,docs)
{
res.render('blog',{"no_of_blogs":docs ,"in_ca":true })
});
});
I have a function that runs on a click, I want this click to redirect to a other view. like a simple link.
how can I render a new view onclick?
node
router.post('/shareinsight', function(req, res, next) {
console.dir(req.body)
var db = req.db_login;
console.log('fs' + req.body.date)
res.redirect('contact');
});
I can see the log in the console so I know that the function is running but it doesn't change view
Try to use this code:
router.post('/shareinsight', function(req, res, next) {
console.dir(req.body)
var db = req.db_login;
console.log('fs' + req.body.date)
res.writeHead(302, {
'Location': 'url'
});
res.end();
});
I am making a wikipedia clone for a project. My initial edit Route looks like this:
router.get('/edit/:id', function(req, res){
var id = req.params.id;
console.log(id);
models.Page.findById(id, function(err, doc){
console.log(doc);
res.render('edit', {page: doc});
});
});
All I am doing is creating an edit page view for a Page with matching id of the id params.
This works until...
I had to add this new route:
router.get('/:url_name/:id', function(req,res){
var id = req.params.id;
models.Page.findById(id, function(err, doc){
res.render('show_page', {page: doc});
});
});
Now when I have this route active, my edit/:id page route doesn't collect the id parameter(req.params.id).
I am lost on why this isn't working and where I should start trying to debug because I am not getting any errors, it will still take me to my edit/:id page, but when I console.log(id) I do not receive a value, or even and undefined, nothing. Furthermore, the {page:doc} I am passing to my edit view is not being found.
If anyone can provide insight or a place to start looking to debug, I'd appreciate it. Just a reminder, the edit/:id route works as it should (req.params.id grabs the id) when I don't have the :url_name/:id route active.
Current Routes -
I added var wiki_routes = require('./routes/wiki'); in my app.js and in that route I have:
// **** URL ROUTES ****
router.get('/', function(req, res) {
models.Page.find(function(err, docs) {
res.render('index', { docs: docs });
});
});
router.get('/:url_name', function(req, res){
var url_name = req.params.url_name;
var isUpdated = req.query.updated;
var updated = (isUpdated === 'true')?true:false;
models.Page.find({url_name: url_name}, function(err, page){
if(page.length > 1){
console.log(page);
res.render('disambiguation', {pages: page, updated: updated });
} else {
console.log(page);
res.render('show_page', {page: page[0], updated: updated});
}
});
});
router.get('/:url_name/:id', function(req,res){
var id = req.params.id;
models.Page.findById(id, function(err, doc){
res.render('show_page', {page: doc});
});
});
// **** EDIT ROUTES ****
router.get('/edit/:id', function(req, res){
var id = req.params.id;
console.log(id);
models.Page.findById(id, function(err, doc){
console.log(doc);
res.render('edit', {page: doc});
});
});
router.post('/edit_submit/:id', function(req, res){
var id = req.params.id;
var new_title = req.body.title;
var new_body = req.body.body;
console.log(req.body);
models.Page.findByIdAndUpdate(id, {title: new_title, body: new_body }, function(err, docs){
// redirects to the wiki page
res.redirect('/wiki/'+ docs.url_name +'?updated=true');
});
});
// **** DELETE ROUTE ****
router.get('/delete/:id', function(req, res){
var id = req.params.id;
models.Page.findByIdAndRemove(id, function(err, data){
res.redirect('/?deleted=true');
});
});
Routes are set up as they occur in the code, as node will give presedence to whichever route it encounters first, so order matters a lot when you're setting up your routes.
An URL could potentially match several routes, especially when using variables that catch a large number of different URL's, or static routes etc.
Say in your case you have an URL that looks like
http://example.com/edit/1234
That URL would most certainly be caught by this route
router.get('/:url_name/:id' ....
as it matches the http://example.com/something/something layout, and it would also be caught by the following route
router.get('/edit/:id', ....
as it matches the http://example.com/edit/something layout.
What route actually cathes the URL depends on the order they where encountered when set up, whichever route that was declared first will catch the URL.
Just shifting the order of the routes will in most cases solve issues like this
// if the URL matches, this will execute first
router.get('/edit/:id', function(req, res){
// do stuff
});
// You'll only get here if the URL doesn't match the above route
router.get('/:url_name/:id', function(req, res){
// do stuff
});
There is a workaround if you simply can't swap the routes around, using the next() callback, like this
router.get('/:url_name/:id', function(req, res, next){
if ( req.params.url_name == 'edit' ) {
next(); // this sends the request back to look for routes below this one
}else{
// do stuff
}
});
router.get('/edit/:id', function(req, res){
// now we'll get here when the "url_name" is "edit" ...
});