Express Router doesn't route as expected - javascript

Running NodeJS on Ubuntu 20.04.2, using VSApp with the debugger
I have the following file named /src/routes/regions.js:
const router = require('express').Router()
const { int } = require('neo4j-driver')
const { required, optional } = require('../middleware/auth')
const { check } = require('express-validator')
const validate = require('../middleware/validate')
const neo4j = require('../neo4j')
const Joi = require('joi');
const Region = require('../entities/Region')
router.get('/1', (req, res, next) => {
return req.neo4j.read(`
MATCH (regions:Region)
return regions order by regions.name ASC
`, params)
.then(regions => res.send(regions))
.catch(e => next(e))
})
router.get('/', (req, res, next) => {
return req.neo4j.read(`
MATCH (regions:Region)
return regions order by regions.name DESC
`, params)
.then(regions => res.send(regions))
.catch(e => next(e))
})
router.get('/:name', (req, res, next) => {
const params = {
name: req.params ? req.params.name : null
}
return req.neo4j.read(`
MATCH (region:Region { name: $name }) return region
`, params)
.then(regions => res.send(regions))
.catch(e => next(e))
})
module.exports = router;
From a browser, if I enter localhost:3000/regions I receive the list of all the Regions in Descending order.
But if I try to enter localhost:3000/regions/1 I receive nothing. The only difference between the two calls should be the order of the received data. The same for localhost:3000/regions/Lazio
It looks like it is not able to recognize patterns in the provided URL
The other really strange behavior is that if I set a breakpoint on any line of the file, the debugger doesn't stop. It looks like it is running another program ....
Can someone help?

Your first route needs to include the name parameter. Express routes aren't inclusive of any others defined elsewhere, so you need to spell it out a bit.
router.get('/:name/1', (req, res, next) => {

Related

I don't understand why it's looking for an ID instead of a view

I'm trying to get a to a certain route, which contains a form, but for some reason it is looking for an id. I'm going to share my routes, my views and the error.
//celebrities routes
const express = require('express');
const router = express.Router();
const Celeb = require('../model/celebrity.model')
router.get('/celebrities', (req, res) => {
Celeb.find()
.then(AlltheModels => {
console.log(AlltheModels)
res.render('celebrities/index', { celebs: AlltheModels })
})
.catch(error => console.log('error while getting the celebrities', error))
})
router.get('/celebrities/:id', (req, res) => {
const celebId = req.params.id
console.log(celebId)
Celeb.findById(celebId)
.then(OneCeleb => {
console.log(OneCeleb)
res.render('celebrities/show', { celebOne: OneCeleb })
})
.catch(error => console.log('there was an error by retrieving..', error))
})
//NEW celebrities
router.get('/celebrities/new', (req, res) => {
res.render('celebrities/new')
})
router.post('/celebrities', (req, res) => {
const { name, occupation, catchPhrase } = req.body;
Celeb.create({ name, occupation, catchPhrase })
// .then(CelebNew => {
// CelebNew.save()
// console.log(CelebNew + '...has been entered')
// })
.then(() => res.redirect('/celebrities'))
.catch(error => `There was an error of ${error}`, err)
})
module.exports = router;
Here's the view that should lead to the form view
<div>
Create a new Celebrity
</div>
<div>
{{#each celebs}}
<a href="/celebrities/{{_id}}">
<h2>{{this.name}}</h2>
</a>
{{/each}}
</div>
and here's the error
"GET /celebrities/new - - ms - -
...there was an error by retrieving.. CastError: Cast to ObjectId failed for value "new" at path "_id" for model "Celeb"
at model.Query.exec (/mnt/c/Users/carlo/documents/ironhack/labs/lab-mongoose-movies/starter-code/node_modules/mongoose/lib/query.js:4408:21)"
from what I understand, the problem lies in this route
router.get('/celebrities/:id', (req, res) => {
const celebId = req.params.id
console.log(celebId)
Celeb.findById(celebId)
.then(OneCeleb => {
console.log(OneCeleb)
res.render('celebrities/show', { OneCeleb })
})
.catch(error => console.log('there was an error by retrieving..', error))
})
but I have no clue why or where the error is, or why it is trying to look for an Id of new, is it the handlebars helpers?.
Your problem is that the path /celebrities/new matches the pattern /celebrities/:id.
When you make a GET request to the path /celebrities/new, Express looks through all of the registered routes, in order, trying to find a match. When Express finds the registered route, /celebrities/:id it considers this a match because the request path matches the pattern - it starts with "/celebrities/" and is followed by an arbitrary string value which it interprets as the id param ("new").
Express will never serve the /celebrities/new GET route because /celebrities/:id will always be the first match.
In order to have Express find the /celebrities/new route, it must be registered before the /celebrities/:id route. You literally just need to move the router.get('/celebrities/new'... code above the router.get('/celebrities/:id',... code.

How to make query request using ExpressJS

what command I should write in ExpressJS file just so that exposes a single HTTP endpoint (/api/search?symbol=$symbol&period=$period)
Working
app.get('/api/search/', (req, res) => {
res.send(req.query)
})
Not working:
app.get('/api/search?symbol=$symbol&period=$period', (req, res) => {
res.send(req.query)
})
app.get('/api/search?symbol=$symbol&period=$period', (req, res) => {
res.send(req.query)
})
In place of this, you have to write below code
const note = require('../app/controllers/note.controller.js');
// Create a new API CALL
app.get('/comment/get', note.index); // In socket.controller.js i have function with the name of index
//note.controller.js file code
exports.index = (req, res) => {
var requestTime = moment().unix();
req.body = req.query;
console.log(req.body); // you will able to get all parameter of GET request in it.
}
Let me know if i need to explain more about
And for sample code of express for API you can view this...
https://github.com/pawansgi92/node-express-rest-api-sample
What I think you're looking for is this:
app.get('/api/search', (req, res) => {
let symbol = req.query.symbol
let period = req.query.period
})
So when you navigate to /api/search?symbol=foo&period=bar
req.query.symbol is "foo"
and req.query.period is "bar"

Can't get single category - NodeJs API

I working on my API for the E-commerce app in MERN. I have done a few things already, and now I am trying to get single category. There is no error on console, and I read the code a few times, but postman keeps throwing Cannot GET error. I would appreciate it if someone can tell me what's the deal with this.
The part for creating new category works just fine, also as similar code for getting one product Code:
Category.js Router
const express = require("express");
const router = express.Router();
const { create, categoryById, get } = require("../controllers/category");
const { requireSignin, isAuth, isAdmin } = require("../controllers/auth");
const { userById } = require("../controllers/user");
router.get("/category/:categoryId", get);
router.post("/category/create/:userId", requireSignin, isAuth, isAdmin, create);
router.param("categoryId", categoryById);
router.param("userId", userById);
Category.js Controller
const Category = require("../models/category");
const { errorHandler } = require("../helpers/dbErrorHandler");
exports.categoryById = (req, res, next, id) => {
Category.findById(id).exec((err, category) => {
if(err || !category) {
return res.status(400).json({
error: 'Category does not exist'
});
}
req.category = category;
next();
});
}
exports.create = (req, res) => {
const category = new Category(req.body);
category.save((err, data) => {
if (err) {
return res.status(400).json({
error: errorHandler(err)
});
}
res.json({ data });
});
};
exports.get = (req, res) => {
return res.json(req.category);
}

Avoid repetitive functions in a controller file inside an express REST API

I have a bunch of controller functions that do exactly the same thing: call a service function in another file of the same name. For the sake of example, I'll provide just two functions, but imagine there are several of them.
const express = require('express');
const router = express.Router();
const userService = require('./user.service');
const authorize = require('_helpers/authorize');
// routes
router.post('/authenticate', authenticate);
router.post('/create', create);
// ...
// ( it goes on like this )
// ...
module.exports = router;
function authenticate(req, res, next) {
userService.authenticate(req.body)
.then(user => user ? res.json(user) : res.status(400).json({ message: 'Error.' }))
.catch(err => next(err));
}
function create(req, res, next) {
userService.create(req.body)
.then(user => user ? res.json(user) : res.status(400).json({ message: 'Error.' }))
.catch(err => next(err));
}
// ...
// ( it goes on like this )
Is there a way in Javascript to avoid such repetitive code? ( I'm not new to programming but I'm a newcomer to Javascript ). I was thinking about automating this code generation with vim macros but maybe there's some package or feature in the language that can make this code look less verbose, maybe some sort of metaprogramming.
Create two utility functions, like this
handleUser which takes a res object and returns another function that takes user. This will allow you to inject res easily
handleError which takes a next callback and return another function that takes err
const handleUser = res => user =>
user ? res.json(user) : res.status(400).json({ message: 'Error.' });
const handleError = next => err => next(err);
const authenticate = (req, res, next) =>
userService.authenticate(req.body)
.then(handleUser(res)).catch(handleError(next));
const create = (req, res, next) => userService.create(req.body)
.then(handleUser(res)).catch(handleError(next));

Mongoose Add If To Middleware

I am not sure if this is a Mongoose or Nodejs Express error?
I would just like to know if there is a way to add middleware in the form of an if. This is my call:
app.post(pPath, auth, (req, res) => {
...
})
And I would just like to do something like this:
app.post(pPath, varBoolean ? auth : null, (req, res) => {
...
})
The above example does not work though. Any idea how I can do this?
Express methods don't support non-function handlers. This is generally a good thing because this allows to detect problems with imports on application start.
This can be achieved with a spread:
app.post(...[pPath, varBoolean && auth, (req, res) => {
...
}].filter(Boolean))
You should try using 'app.use', if you want to have a middleware in place.
app.use('/path', (req, res, next) => {
const { test } = req.body;
const { auth } = req.headers;
if(!test) {
return res.status(400).json({message: 'Missing field test'});
}
const validToken = await tokenValidation(auth);
if(!validToken){
return res.status(403).json({message: 'Unauthorized'});
}
next();
});

Categories

Resources