I have two routes: /news and /news-paginate (I know it is a not good URL but it doesn't matter atm). In the news route, I load 5 records from the database and render a populated view. In the /news-paginate route, I load other 5 records based on the page number and size sent from the client; this route responds with a JSON object.
news route
router.get('/news', function (req, res) {
...
connection.query(queries['news_list'], [language, +pageSize, +offset], function (err, rows) {
res.render('news', {news: rows});
});
});
news-paginate route
router.get('/news-paginate', function (req, res) {
var language = 'RU';
var pageSize = req.query.pageSize;
var pageNumber = req.query.pageNumber;
var offset = (pageNumber - 1) * pageSize;
connection.query(queries['news_list'], [language, +pageSize, +offset], function (err, rows) {
res.json(rows);
});
});
I am concerned about my architecture. Is my approach correct? I have two routes with the same functionality and different responses. Should I somehow combine these two routes into one?
Hmm, I usually have a single route, in your case /news which can receive 2 optional params: pageSize, pageNumber for your pagination purposes. If those params don't exists than you will offer the first 5 records. If those params are present than you will start providing the other 5 records and based on the calculated offset.
router.get('/news/:pageSize?/:pageNumber?', function (req, res) {
var language = 'RU';
var pageSize = req.params.pageSize || 5;
var pageNumber = req.params.pageNumber || 1;
var offset = (pageNumber - 1) * pageSize; // If no params are provided than the offset should be 0
connection.query(queries['news_list'], [language, +pageSize, +offset], function (err, rows) {
res.json(rows);
});
});
I am not familiar with optional params in express routes but I hope you get the main idea behind the approach.
You can do ajax requests to load the extra records after the first 5 records are listed.
I hope this shined a light on the approach.
Related
So I have an issue with Express.Js currently. When I goto /article/14 it returns with these as the parameter.
{ artId: '14' }
{ artId: 'img' }
However, I'm not sure where it gets the img part from or how the value is there twice. However, if I go to a different Id article it works fine.
This is the full code
app.get('/article/:artId', async function (req, res) {
let artId = req.params.artId;
getDiscordUserInfo(req, res, function(disData) {
connection.query(`SELECT * FROM articles WHERE id = ${artId}`, (err, artResults) => {
if(artResults[0]) {
connection.query(`SELECT * FROM articles WHERE deleted = 0 AND catId = ${artResults[0].catId}`, (err, catArtsResults) => {
connection.query(`SELECT * FROM categories WHERE id = ${artResults[0].catId}`, (err, resultsCat) => {
res.render('article', {discordInfo: disData, siteInfo: config['siteInformation'], art: artResults[0], catArts: catArtsResults, cat: resultsCat[0], mdConvert: md});
});
});
} else {
res.redirect('/');
}
});
});
});
It also seems to still load the page and then crash because of img.
Seems to be resolved. To make the articles I use a markdown converter and the image I placed in the body of the page seems to be the cause. I didn't have the link yet so I used img as a placeholder in the code which made this the result;
Not sure how this in the body would be a cause but somehow was.
aha,,,
app.get('/article/:artId')
:artId is dynamic params.
so if you have the same route maybe in your case
app.get('/article/:artId') // route 1
app.get('/article/img') // route 2
simple solution just add conditon before query to database
if(artId !== "img")
Problem
Hi devs,
I am having trouble passing an id that has a '/' at the beginning.
This is the log
GET /api/v1/ GetAnimeInfo//anime/5226/tokyo-ghoul/Tokyo% 20Ghoul 404 0.466 ms - 1310
As you can see, He can not recognize two / after GetAnimeInfo//
Isn't there a way expressjs allows me that pattern?
//id = '/anime/5226/tokyo-ghoul/'
//title = 'Tokyo Ghoul'
router.get('/GetAnimeInfo/:id([^/]+/[^/]+[^/]+/[^/])/:title' , (req , res , next) =>{
let id = req.params.id
let title = req.query.title;
api.getAnimeInfo(id , title)
.then(info =>{
res.status(200).json({
info
});
}).catch((err) =>{
console.log(err);
});
});
I would highly advise against doing this.
If a client is sending an erroneous double slash there is a functional bug creating that issue and you should fix the bug, not provide a weird workaround on the server - that way you end up with more robust, predictable and maintainable code in the future.
If you're trying to manipulate the server to accept double slash as part of routing, there will be no guarantee that clients will respect the behavior so you will run into situations where one browser will work and another will not.
If you have shows which begin in a slash, eg '/ShowName', that you need to account for, you should be escaping the show name with URL encoding - https://en.wikipedia.org/wiki/Percent-encoding
Yeah, that's unlikely to work given Express would have no idea where where the :id ends and where the rest of the URL pattern match begins.
Can't you just parse the URL manually? Doesn't seem like it would be all that difficult e.g.
router.get('/GetAnimeInfo/:idAndTitle', (req, res, next) => {
const { idAndTitle } = req.params;
const idx = idAndTitle.lastIndexOf("/") + 1;
const id = idAndTitle.substring(0, idx);
const title = idAndTitle.substring(idx, idAndTitle.length);
...
});
Demo
const idAndTitle = '/anime/5226/tokyo-ghoul/Tokyo Ghoul';
const idx = idAndTitle.lastIndexOf("/") + 1;
const id = idAndTitle.substring(0, idx);
const title = idAndTitle.substring(idx, idAndTitle.length);
console.log(`ID=${id}`);
console.log(`Title=${title}`);
I am trying to add paging using express-paginate module. But i am getting limit parameter in url like this: http://example.com:3010/feeds?page=2&limit=10.
But i don't want to use limit in url. How i can remove limit from url?
Below is my pug file code.
if paginate.hasPreviousPages || paginate.hasNextPages(pageCount)
.navigation.well-sm#pagination
ul.pager
if paginate.hasPreviousPages
li.previous
a(href=paginate.href(true)).prev
i.fa.fa-arrow-circle-left
| Previous
if pages
each page in pages
a.btn.btn-default(href=page.url)= page.number
if paginate.hasNextPages(pageCount)
li.next
a(href=paginate.href()).next
| Next
i.fa.fa-arrow-circle-right`
I think you can add this by creating a simple middleware function, e.g.
const app = express();
const DEFAULT_PAGE_COUNT = 10;
// Intercept all calls and add a default page count.
app.use(function(req, res, next) {
if (!("limit" in req.query)) {
req.query.limit = DEFAULT_PAGE_COUNT;
}
next();
});
And actually, I believe the module supplies this middleware function, e.g.
// keep this before all routes that will use pagination
// paginate.middleware(limit, maxLimit)
const paginate = require('express-paginate');
app.use(paginate.middleware(10, 50));
var s_bookingController = require('s/controllers);
app.get('/dashboard/:page/:param', s_bookingController.index)
app.get('/dashboard/show/:id', s_bookingController.show);
Controllers:
exports.index = function(req, res, next) {
var page = parseInt(req.param("id"));
data = {};
data.page = page;
data.nextPage = page + 1;
data.prevPage = page - 1;
MyModel.find().sort('brand').skip((page-1)*11).limit(11).exec(function(err, result) {
res.render('index', {
data: data,
booking: result,
});
});
};
And
exports.show = function(req, res, next) {
var id = req.param("id");
res.send(id);
};
I'm using this controllers, but there is something wrong with the code of the exports.index, because it's stuck in the code.
If I change the routes to:
app.get('/dashboard/:page', s_bookingController.index)
(Note that I'm take off the second parameter that I was passing)
the show will work, but if I use the second parameter, the show will not run, it will be stuck in the index page.
Why is this? I was wondering if I need use the next();.
Expanding my comment:
You should have the following order of the routes:
app.get('/dashboard/show/:id', s_bookingController.show);
app.get('/dashboard/:page/:param', s_bookingController.index);
Express routing requires that a more specific route should be placed above the more general one.
The /dashboard/show/:id is more specific in this case as /dashboard/:page/:param covers it, so that /dashboard/show is handled by it. When the route is handled next routes are not executed.
What I am trying to do:
Using middleware function I want to store user data from session in to locals so I can use it later in my views without store those data in every method / controller.
Instead of (in every method / controller):
function(req, res){
data.user = req.session.user;
res.render('someView', data);
}
and in View (template):
<div>
#model.user.username
</div>
i want to define middleware like this:
if (req.session.user) {
var now = new Date().getTime();
var data = req.session.user;
var timeout = data.loggedIn + config.auth.timeout;
if (timeout < now) {
req.session.user = null;
reg.flash('errors', {
param: 'default',
msg: 'Your session is expired...'
});
return res.redirect('/login');
}
res.locals.user = sesData;
}
return next();
and in view display my data from res.locals. And there is my BIG questionmark... is it possible ?
I could find any information how to display data from res.locals in vash views.
Am i missing something, is my solution plausible ?
UPDATE
Finally i found solution. Displaying app.locals in VASH views is quite simple :-)
View:
<div>
#model._locals.user.username
</div>
would do what i need :-)
I hope someone will find it useful.