How to pass variable to express routes? - node.js

I'm making a website where i need an id passed to an express route.
I have a button (id='approve_appln') which fetches a route. The javascript involved is as follows:
var appr_appln = document.getElementById('approve_appln');
appr_appln.addEventListener('click', function(e) {
var approve_id = appr_appln.getAttribute('data');
fetch('/approved', {method: 'POST'})
.then(function(response) {
if(response.ok) {
alert(approve_id);
return;
}
throw new Error('Request failed.');
})
.catch(function(error) {
alert('error');
});
});
I need to pass the approve_id variable to the /approved route. The route is now empty though:
app.post('/approved',function(req,res){
});
How do I pass the approve_id variable so it can be used to refer a particular object in my database?

Your endpoint can have an id attached to it
for example:
app.post('/approved',function(req,res){
});
should be
app.post('/approved/:id',function(req,res){
const id = req.params.id // This is how you access URL variable
});
Keep in mind :id here is a variable that can be replaced by an actual ID when requesting from URL.
for example you can do something like this ```http://localhost/approved/1231451324123
so to follow your example, you can just send the ID with the URL by doing something like this
var appr_appln = document.getElementById('approve_appln');
appr_appln.addEventListener('click', function(e) {
var approve_id = appr_appln.getAttribute('data');
fetch(`/approved/${approve_id}`, {method: 'POST'})
.then(function(response) {
if(response.ok) {
alert(approve_id);
return;
}
throw new Error('Request failed.');
})
.catch(function(error) {
alert('error');
});
});
note I only changed this line fetch('/approved', {method: 'POST'})
I replaced single quotes ' with ` so I can concatenate easier. also ${} means I can add any CODE inside these brackets.
Good luck, if you need more explanation let me know.

Related

How to send a NODE.JS post request from an Angular Project?

I have a NODE.JS api using expressjs that connects to an SQL Server, and I want to use it in an angular project. I make use two files, a route file and a controllers file. My route file is as follows:
module.exports = (app) => {
const UsrContrllr = require('../Controllers/users.controllers');
//1. GET ALL USERS
app.get('/api/users', UsrContrllr.func1);
//2. POST NEW USER
app.post('/api/user/new', UsrContrllr.func2);
};
And my controllers file is given below:
const mssql = require('mssql');
exports.func1 = (req, res) =>
{
// Validate request
console.log(`Fetching RESPONSE`);
// create Request object
var request = new mssql.Request();
// query to the database and get the records
const queryStr = `SELECT * FROM USERS`;
request.query(queryStr, function (err, recordset) {
if (err) console.log(err)
else {
if (recordset.recordset.toString() === '') {
res.send('Oops!!! Required data not found...');
}
else {
// send records as a response
res.send(recordset);
}
};
});
};
exports.func2 = (req, res) =>
{
// Validate request
console.log(`INSERTING RECORD ${req}`);
// create Request object
var request = new mssql.Request();
// query to the database and get the records
const queryStr = `INSERT INTO GDUSERS (USERCODE, PASSWORD, LANGUAGE, USERCLASS, FIRSTNAME, LASTNAME, CONTACTNO) VALUES ('${req.body.usercode}', '${req.body.password}', 'EN', '0', '${req.body.firstname}', '${req.body.lastname}', '${req.body.contactno}');`;
request.query(queryStr, function (err, recordset) {
if (err) console.log(err)
else {
if (recordset.recordset.toString() == '') {
res.send('Oops!!! Required data not found...');
}
else {
// Send records as response
res.send(recordset);
}
};
});
};
The GET request works well, but when I try to run the POST request directly from the angular application, I get an error stating
Cannot GET URL/api/user/new
The angular code in my angular project is:
signup() {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
console.log(this.user); //User details come from a form
this.http.post(“URL", this.user, options)
.subscribe(
(err) => {
if(err) console.log(err);
console.log("Success");
});
}
I’m not sure whether the angular code I’m using, is right or not, and I don’t know where I’m going wrong. How does one exactly send a http POST request from an Angular project?
this i the way i handled my user signup with http.post calls. my approach is slightly different when signing up user because i am using a promise instead of observable (which i normally use for my servicecalls). but i will show you both ways.
createUser(user: User): Promise < string > {
const promise = new Promise < string > ((resolve, reject) => {
const userForPost = this.createUserForPost(user);
this.http.post(environment.backendUrl + '/api/user/signup', userForPost, this.config).toPromise < HttpConfig > ()
.then(createdUser => {
}).catch(error => {
console.log(error);
});
});
return promise;
}
here another example with an observable
createForumPost(forumPost: ForumPost) {
this.http.post < { message: string, forumPostId: string } > (environment.backendUrl + '/api/forumPosts', forumPost).subscribe((responseData) => {
const id = responseData.forumPostId;
forumPost.id = id;
});
}
i defined my URL somewhere else and then just use the environment.backedUrl + 'path' to define my path (the same as the path in your backend controller)
this is one of my first answers here on SO. i am sry if it is a bit messy
i hope i was able to help with my examples :)

'ERR_HTTP_HEADERS_SENT' after POST request in Node.js/ Express app with request http client

The line res.send("Successfully saved the new address."); throws the
'ERR_HTTP_HEADERS_SENT' error.
I read through other posts concerning the same error and tried return res.send("Successfully saved the new address."), but that doesn't fix it. Any insights?
Note: I am new to this.
Please be kind.
Thanks.
My Code
app.post("/", function(req, res) {
const url = "http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates?";
const street = req.body.street;
const city = req.body.city;
const state = req.body.state;
const zip = req.body.zip;
const yourAddress = "Address=" + street.replace(" ", "+") + "&City=" + city.replace(" ", "+") + "&Zip=" + zip;
const parameters = "&category=&outFields=*&forStorage=false&f=json";
request(url + yourAddress + parameters, function(error, response, body) {
const data = JSON.parse(body);
const newAddress = data.candidates[0].address;
const longitude = data.candidates[0].location.x;
const latitude = data.candidates[0].location.y;
const address = new Address({
address: newAddress,
latitude: latitude,
longitude: longitude
});
address.save(function(err) {
if (!err) {
res.send("Successfully saved the new address.");
} else {
res.send(err);
}
});
});
res.redirect("/");
});
You are doing both res.send() and res.redirect() in the same request handler. You can't send two responses to the same request. That's what generates the warning message you see.
Pick one of the other. You either want to send an appropriate status about the .save() or you want to redirect. One or the other, not both.
In this particular code, the res.redirect() happens first so it's what the client sees. Then, after that and when the request() and the address.save() have both completed, then you try to res.send(), but that is blocked because a response has already been sent and the http connection is already done.
If you just want to redirect upon successful save, you can remove the existing res.redirect() and change to this:
address.save(function(err) {
if (!err) {
res.redirect("/");
} else {
console.log(err);
res.sendStatus(500);
}
I would Agree With #jfriend00 answer , since there can be only one response for the request .
Here's what you can do:
address.save(function(err) {
if (!err) {
res.redirect('/success')
} else {
res.send(err);
}
});
//add a new route
app.get('/success',(req,res)=>{res.send('Successfully saved the new address.')})
And then you can redirect to the home page.
This is just a workaround in this case and can differ logically in each case depending on the requirement
The Other Way is to redirect on the client side itself
eg:If you're on jquery
$.ajax({
statusCode: {
200: function() {
$(location).attr('href', 'to the homepage')
}
}
});

How do I rewrite a request URL and keep info in same request with express?

I have a REST API for songs resources, they got an id and a title, admins can perform GET /songs/:id directly, but common users can only access through GET /songs/:title.
So if a common user tries to access to a resource like:
{
"id":9248,
"title": "Hala Madrid"
}
By requesting GET /songs/9248 he should be redirected to GET /songs/hala_madrid.
So I could have two different route handlers, and repeat the query. But I really don't want to query twice. So I thought I could reset url and assign the found song to req.song.
I tried setting up the following routes and implement a single get controller method:
router.get('/:id([0-9]+)', songs.get);
router.get('/:title', songs.get);
function get(req, res, next) {
let { id, title} = req.params;
console.log(id, title);
let permalink = id || title;
let field = isNaN(permalink) ? 'title' : 'id';
if (req.song) {
let { song } = req;
return res.render('app', {song, title: 'song', page: 'song'});
}
queries.getSong(field, permalink).then(result => {
let song = result[0];
if (req.session.user.role === 'user' && field === 'id') {
req.song = song;
req.url = `/songs/${song.title}`;
return next();
}
return res.render('app', {song, title: 'song', page: 'song'});
})
.catch(err => {
console.error(err);
return res.status(500).json({error: err});
});
}
I'm a bit lost as it's ending up in unhandled error, I dont know how reload the request to be handled again.
Maybe I'm misunderstanding something but do you have to have two parameters?
router.get('/songs/:idortitle', function(req,res,next) {
const permalink = req.params.idortitle;
const songQuery !isNaN(permalink) && !req.session.user.role ==='user' ? queries.getSong('id',permalink) :queries.getSong('title',permalink);
songQuery.then(result => {
res.render('app', {song, title: 'song', page: 'song'});
}).catch(e => {
console.error(err);
return res.status(500).json({error: err});
});
});
This case just checks if the parameter is a number and the user is not 'user' (then its admin I assume) and then queries by id. Otherwise it queries by title
so /songs/9248 and /songs/hala_madrid works

Why can't Restful pass body into database

I'm creating a RESTful API.
I wanna use GET method to check if lastName exists. If it can find lastName, return "YES", otherwise, call a POST method to create a data with lastName entered.
The problem is that it can create a new data, but the body is empty. Ideally, it should contain a value with lastName, like "lastName": "James",
{
"_id": "58a22c3c3f07b1fc455333a5",
"__v": 0
}
Here is my code.
router.route("/findLastName/:id")
.get(function(req,res){
var response;
mongoOp.findOne({deviceID: req.params.id}, function(err, result){
if (err) {
response = {"error" : true,"message" : "Error fetching data"};
res.json(response);
}
if (result) {
response = "YES";
res.send(response);
} else {
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
var xhr = new XMLHttpRequest();
var POSTurl = "http://localhost:6002/users";
var params = "lastName=" + req.params.id;
xhr.open("POST", POSTurl, true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(params);
}
});
})
PS: GET method works well, not a issue.
Let me modify a bit of your code and add comments as pointers:
// changed findLastName to find-last-name. It's a common convention,
// urls need to be case insensitive. It doesn't concern lastName, as
// that's a parameter, internal to your app so it's fine.
// even better if you name the route `find-or-create` or something, to better
// reflect what you're doing.
router.route("/find-last-name/:lastName")
.get(function(req,res){
var response;
mongoOp.findOne({deviceID: req.params.lastName}, function(err, result){
if (err) {
response = {"error" : true,"message" : "Error fetching data"};
// Adding a `return statement here. If you don't return, you'll tell
// the user that there was an error, but your code continues running
// potentially calling that res.json twice.
// Also, since it's an internal error, it's common to tell the client
// about it, by setting the status to 500
return res.status(500).json(response);
}
if (result) {
// turning the message to JSON instead. You started that above,
// and for the sake of your clients (your frontend), it's
// better to stick to JSON. Also you can pass useful info, such as
// _id of the document.
// Again adding a `return` here, and then the rest of the code
// is nested one level less. not required, but some people like that.
response = {
message: "Last name exists."
};
return res.json(response);
}
// Here begins the new code. I'm typing what I can infer from your code,
// I don't know if your MongoDB driver looks like that exactly.
mongoOp.insert({
deviceId: req.params.lastName
// add other optional properties here.
}, function (err, response) {
if (err) {
var message = {
error: true,
message: 'Cannot save new entry.'
}
return res.status(500).json(message);
}
// if we're here, everything went ok. You can probably return
// the _id of the given user.
return res.json({
message: 'New user created.',
_id: response._id
});
});
});
})

Angularjs passing variables from controller to dao service

I am trying to pass a variable from the controller to my DAO service in an Angularjs application (frontend) and nodejs backend.
here is my controller :
$scope.afficherProfils = function() {
$http.get(configuration.URL_REQUEST + '/profile')
.success(function(data) {
$scope.owner = data._id;
console.log('$scope.owner =========>');
console.log($scope.owner);
$http.get(configuration.URL_REQUEST + '/listerProfil', {
owner: $scope.owner
})
.success(function(data) {
console.log('$scope.listeProfils =========>');
console.log(data);
$scope.listeProfils = data;
});
});
};
i am calling /profile to get the _id of the account that has added the profile, after that i call /listerProfil inside success and pass the owner parameter.
and in my DAO service the code is the following :
exports.all = function(req, res) {
console.log('req.body ================================>');
console.log(req.body);
Profil.find({
owner: req.body.owner
}, function(err, profils) {
if (err) {
res.send({
'result': 'error'
});
} else {
res.send(profils);
}
});
};
and i don't know why my req.body is empty when i do a console.log
any ideas ?
HTTP-CRUD(Create-$http.post,Read-$http.get,Update-$http.put,Dlete-$http.delet)
$http.get-It used to get the value means this body contain empty value
$http.post-It used to create value means this body contain data (your are post some data to server)
$http.update-It used to update exit value this body also contain data
$http.delete-It used to delete exit value this body contain empty(send through param(?id=1111))
so change your code http.get to http.post

Resources