I am trying to implement routes with classes in my express js application
controller
class User {
constructor (){
this.username = 'me';
}
getUsername(req,res){
res.json({
'name':this.name
});
}
}
export default User;
In my routes
import express from 'express'
import User from './controller'
const router = express.Router();
const user = new User();
router('/',user.getUsername.bind(user));
export default UserRoute
But I got this error
req.next = next;
^
TypeError: Cannot create property 'next' on string '/'
at Function.handle (/var/accubits-workspace/express-es6/node_modules/express/lib/router/index.js:160:12)
you are not using any method on the router object, you need something like get , post, put , delete or other http/https verbs or use for creating middleware.
for example
router.VERB("/", ...);
router.(use HTTP method like(get,post...))('/',user.getUsername.bind(user));
Related
I have a problem with my code TypeScript, am using the library of node gitlab, and have installed the package correctly, so much in #types as in node_modules, am trying to do a CRUD for gitlab, and just now I am fulfilling the backend with express. When the controller to do of gitlab and on having compiled to javascript, he throws error to me:
and here is my code:
// Import only what we need from express
import { Router, Request, Response } from 'express';
import * as gitlab from "gitlab";
// Assign router to the express.Router() instance
const router: Router = Router();
const api = new gitlab({
url: 'http://git.test.com/',
token: 'asdasfgwsgsafa',
});
const users = api.users.all();
router.get('/allUsers', (req: Request, res: Response) => {
res.send(users);
});
// The / here corresponds to the route that the gitLabController
// is mounted on in the server.ts file.
// In this case it's /gitlab
router.get('/', (req: Request, res: Response) => {
// Reply with a hello world when no name param is provided
res.send('Hello, World!');
});
router.get('/:name', (req: Request, res: Response) => {
// Extract the name from the request parameters
res.send(`Hello, ${req.params.name}`);
});
// Export the express.Router() instance to be used by server.ts
export const gitLabController: Router = router;
I hope that they could help me, thank you in advance.
You are importing all the modules from gitlab. You can do
import Gitlab from "gitlab";
Then,
const api = new Gitlab({
url: 'http://git.test.com/',
token: 'asdasfgwsgsafa'
});
Since, you are doing import * as gitlab from "gitlab"; it does not get the gitlab module when you do new gitlab
With the way you have imported you need to do:
const api = new gitlab.Gitlab({
url: 'http://git.test.com/',
token: 'asdasfgwsgsafa'
});
For further reading you can refer here
Let's say I have the following routes:
// routes.js
import PhotoRoutes from './photoRoutes';
const UserBaseRoute = Router();
UserBaseRoute.use('/api/:userId', PhotoRoutes);
// photoRoutes.js
const PhotoRoute = Router();
PhotoRoute.get('/', (req, res) => {
console.log(req.params);
res.end();
});
export default PhotoRoute;
When I hit /api/123/ I expect to use {"userId: 123}' But I don't. Why is the :userId defined in the baseRoute not passed up?
This is a issue related to nested router.
You need to set the mergeParams of child router as true to access params from parent router.
So try following code:
const PhotoRoute = Router({mergeParams: true});
BTW, this option came with Express version 4.5. For more details, refer to the API document
I'm new to mongoose so I apologise for incorrect uses of terminology.
I have a routes file as detailed below
const express = require('express');
const router = express.Router();
const passport = require('passport');
const controller = require('./clubController');
const authGuard = passport.authenticate('jwt', { session: false });
const verifyUser = require('./clubController').verifyUser;
const isSiteAdmin = require('./clubController').isSiteAdmin;
router.param('id', controller.params);
router.route('/')
.post(authGuard, controller.newClub)
.get(controller.allPublicClubs);
router.route('/:id')
.put(authGuard, verifyUser(), controller.editClub)
.get(controller.getClub);
router.route('/private')
.get(controller.allPrivateClubs);
module.exports = router;
controller.params
exports.params = function(req, res, next, id) {
Club.findById(id)
.populate('creator teams', '-password -email -role')
.exec()
.then(function(club) {
if (!club) {
return res.status(404).send({ msg: 'No Club exists with that ID' });
} else {
req.club = club;
next();
}
}, function(err) {
// error handling
next(err);
});
};
controller.params is being fired when I make a get request to /private. To my understanding, the params middleware I have setup should only be fired when a called route is using an id parameter.
The value for the id argument in controller.params is set as private which is the route.
The error I receive is detailed below
CastError: Cast to ObjectId failed for value "private" at path "_id" for model "club"
This was working fine yesterday, no idea what changed that it now does not work.
I solved the issue by moving
router.route('/:id')
.put(authGuard, verifyUser(), controller.editClub)
.get(controller.getClub);
To the bottom of all the routes. Was strange as I had the same order before and it worked fine
i want to perform some validation and addition to the request on specific parameter for a route and all nested routes.
My REST structure is /room/:room/messages
In my main.js
const roomRoute = require('roomroute.js');
const messageRoute = require('messageroute.js');
app.use('/room',roomRoute);
app.use('/room/:room/messages',messageRoute);
in roomroute.js
const express = require('express');
const router = express.Router();
router.param('room', function (req,res,next,id) {
// Just for demo
var room = {
id: id,
title: 'Testroom'
};
req.room = room;
next();
});
router.get('/:room, function (req,res) {
// Display room to console
console.log(req.room);
res.sendStatus(200).end();
});
module.exports = router;
In messageroute.js
const express = require('express');
const router = express.Router({ mergeParams:true });
router.get('/', function(req,res) {
console.log(req.room); // Not working
});
module.exports = router;
When i do a get to a room eg. /room/1234 then req.room is displayed to the console, which actually is want i want.
But when i do a get to eg. /room/1234/messages the route.param('room'... of the parent is not executed, but instead just the get of the messageroute.js.
Is there a way to achieve that the param is evaluated for the parent route and also for all nested routes ?
Thank you,
Stefan
This looks like a misunderstanding of how nested routers work. In your example you seem to be looking to share a param across roomroute and messageroute, however, both of those routers have no relation to eachother.
Routers become nested when they're supplied as middleware to another router - you have an example of this already....app is a router in itself and you nest both roomroute and messageroute into it. So based on your current setup, if you want to share param('room') across both these routes you will need to configure it at app level i.e.
main.js
const roomRoute = require('roomroute.js');
const messageRoute = require('messageroute.js');
app.param('room', function (req,res,next,id) {
// Just for demo
var room = {
id: id,
title: 'Testroom'
};
req.room = room;
next();
});
app.use('/room', roomRoute);
app.use('/room/:room/messages', messageRoute);
roomroute.js
const router = express.Router({ mergeParams: true });
router.get('/:room', ...);
messageroute.js
const router = express.Router({ mergeParams: true });
router.get('/', ...);
This is code from main.js where I`ve configured my router
enter code here
const router = new Router({
routes,
mode: 'history',
saveScrollPosition: true
});
sync(store, router);
const app = new Vue({
router,
store,
render: h => h(App )
}).$mount('#app');
Then in vuex/actions.js I`ve action registerUser where I do request to API and if response is success I want to redirect user to main page
enter code here
export const registerUser = ({commit, state}, userData) => {
commit(types.REQUEST_USER_REGISTER);
api.register(userData).then(success => {
const response = success.data;
localStorage.setItem('id_token', response.token);
commit(types.USER_OBJECT, response.user)
//TODO: find better solution, then put router instance into window var
window.router.replace('/');
}, failure => {
})
}
This code above works well, because I`ve set router instance into window var in build.js, maybe somebody know better solution instead of it
Move router declaration to separate file and export it. Then import in main file and any other file which you wish to use it. The api is the same as for $router property on vue prototype.