how to get id from url in express, param and query doesnt seem to work - node.js

I have a url, i'm trying to get id but none of it is working req.params nor req.query
app.get('/test/:uid', function testfn(req, res, next) {
debug('uid', req.params.uid); // gives :uid
debug('uid', req.query.uid); // gives undefined
});
I'm doing an ajax call like this
$(document).on('click', 'a.testlink', function(e) {
$.ajax({
type: "GET",
url: '/test/:uid',
success: function(var) {
console.log('success');
},
error: function() {
alert('Error occured');
}
});
return false;
});
I'm using
app.use(express.json());
app.use(express.urlencoded());
instead of body parser

Your code is working as expected: The ajax call specifies url: '/test/:uid' which is what puts :uid in req.params.uid.
Try sending something else: url: '/test/123' and req.params.uid will contain 123

Here is an example that will work. I will give step by step instructions from the start:
express myproject
cd myproject
npm install
Open app.js and add in the following somewhere in the file - maybe right before the line app.get('/test/:uid',test);
var test = function(req,res,next) {
// do whatever logic is needed
res.end('Displaying information for uid ' + req.params.uid);
}
app.get('/test/:uid',test);
Now, open up a new terminal, make sure you are in the myproject directory and enter:
node app.js
Now you can visit http://localhost:3000/test/45 on the local machine and you should see:
Displaying information for uid 45
If you are not accessing from your local machine make sure to change the url above to match whatever server your node app is running on.
Also, this is just a simple example. You might be better off organizing everything by placing the routes in files similar to the routes directory example setup in a new install of an express app. You can find more detailed examples of this on the web like this one and this one. Also, one of the best explanations of organizing/reusing code in Node this I have seen is in the book NodeJS in Action.

Related

How to process JS file returned from Express response.sendFile()

I have an API which uses Node.js + Express on the backend.
For one of the API endpoints, I'd like to use the Express response object method of "sendFile", documented here:
https://expressjs.com/en/api.html#res.sendFile
The API should return a Javascript file through the sendFile method.
What I can't figure out is how to read in the .js file on the front end so that I can use the JavaScript functions defined in the file. The sendFile portion appears to be working -- it's just the use of the file which I can't figure out.
Here's what I'm doing on the backend:
app.get("/api/member", async (req, res) => {
options = {
root: path.join(__dirname, '/static'),
dotfiles: 'deny'
}
res.sendFile("member.js", options, (err) => {
if (err) {
console.log(err)
next(err)
} else {
console.log('Sent file')
}
})
});
This seems to be working fine, as I can navigate to the endpoint on my localhost and it loads the JS file. The file member.js simply contains some javascript function definitions.
But, I can't figure out how to consume/use the file once it arrives to the front end.
Here's what I have currently on the frontend:
async function refreshJS() {
const url = `${baseUrl}/member`;
const response = await fetch(url, { credentials: "include" });
const script = document.createElement("script")
script.type = "text/javascript"
script.src = response.body
document.head.appendChild(script)
eval(script)
}
I've spent a lot of time looking through the console/debugger to find the text associated with the JS functions -- but they're nowhere to be found.
I've tested this general framework by loading JS files locally through the console and it worked, so I think it's wrapped up in a misunderstanding of where the JS functions live in the API response. For example, if I replace the command above of:
script.src = response.body
with
script.src = "member.js"
then everything works fine provided I have the file locally.
The examples that I've reviewed seem to deal exclusively with sending an HTML file which is loaded on the frontend. But, I can't find supporting documentation from the fetch API to understand how to use the JS file contents.

Node.js REST API - URI Sanitizing?

I would like to require pages in my Node.js server based on the requested URI.
However I concern that this could be a severe security issue since user can inject some malicous chars into the url, something like ../../ and reach to my root server point and reveal all of the code.
So just like throwing a bottle of water to a big fire, I have eliminated the option to send . to the request.
This is not a silverbullet, probably :)
Maybe is there some standard/best practice/guide or keypoints about URI sanitizing in REST API based on Node.js?
Edit - here the code uses the require
// app.js
app.use(require('./services/router')(app));
// router.js middleware
function router(app) {
return function(req, res, next) {
try {
// checking for . in the url
if (req.url.indexOf(".")!=-1) cast.badRequest();
// req.url.split('/')[2] should be customers, users or anything else
require('../../resources/' + req.url.split('/')[2] + '/' + req.url.split('/')[2] + '-router')(app);
next();
} catch(err) { cast.notFound(); }
}
}
module.exports = router;
// rides-router.js (this could be users-router.js or customers-router.js)
module.exports = function(app) {
// GET ride - select a ride
app.get("/v1/rides/:id", dep.verifyToken(), require('./api/v1-get-ride'));
// POST ride - insert a new ride
app.post("/v1/rides", dep.verifyToken(), require('./api/v1-set-ride'));
app.use((req, res, next) => {
cast.notFound();
});
}
You asked how to do it safer. My recommendation is that you put all the resources in an array and run all the app.use() statements with one loop that pulls the resource names from the array at server startup.
I don't like running synchronous require() during a request and I don't like loading code based on user specified characters. Both are avoided with my recommendation.
// add routes for all resources
const resourceList = ['rides', 'products', ...];
for (let r of resourceList) {
app.use(`/${r}`, require(`./resources/${r}/${r}-router`));
}
This seems like less code and 100% safe and no running of synchronous require() during a request.
Advantages:
Fully whitelisted.
No user input involved in selecting code to run.
No synchronous require() during request processing.
All routes installed at server initialization time.
Any errors in route loading (like a missing route file) occur at server startup, not during a user request.

Forever module with node app executable file

I am working on Node JS application.
In this I have to check first user is connected with internet or not. If yes then check KinectRuntime-v2.0_1409-Setup installed or not.. and further more such kind of validations are there. so I have used the following code in my entry script:
What I have Done:
broadcast.js: // entry file which we use to start app
var tempkinect = require('./controllers/tempkinect.js');
tempkinect.controller(app);
require('dns').lookup('google.com',function(err) {
if (err){
server.listen(8000, function(req, res){
open('http://localhost:8000/internetnotfound'); // internet not found page.
return false;
});
}
else{
try{
var Kinect2 = require("kinect2");
var kinect = new Kinect2();
}
catch(ex) {
server.listen(8000, function(req, res){
open('http://localhost:8000/kinectnotfound');
open('https://www.microsoft.com/en-in/download/confirmation.aspx?id=44559');
return false;
}
} //else ends here
});
tempkinect.js file: // my controller file
module.exports.controller = function(app){
app.get('/kinectnotfound',function(req,res){
var errmsg = "KinectRuntime-v2.0_1409-Setup not installed on your computer. Download will start automatically, if not then";
var link = "https://www.microsoft.com/en-in/download/confirmation.aspx?id=44559";
var click = "Click Here!"
res.render('initialerror',{errormessage:errmsg, downloadlink : link, clickhere: click, title : 'Kinect Not Found'});
});
app.get('/internetnotfound', function(req,res){
require('dns').lookup('google.com',function(err) {
if (err){
res.render('initialerror',{errormessage:'Please Connect Internet for Login.',downloadlink : '', clickhere : '', title : 'Internet Not Connected'});
}
else{
res.redirect('/restart');
}
});
});
app.get('/restart', function (req, res, next) {
process.exit(1);
});
}
I am using enclose module which compiled the node js application and creates .exe file. Now, If I run application on my local machine using command prompt:
run > node broadcast.js
then in case of internet not found app displays corresponding page.( then I connect internet manually ) after connecting internet when I refresh the page it restarts the process, which is good as per required.
BUT, when I do the same using compiled application then it is giving me error:
What Error I am getting:
So can anyone please suggest what should be modified there?
Besides this, Forever should be installed as global on the system so it is working fine on my system but not on others with the compiled app.
Looks like you already have something running at port 8000 (possibly other copy of your app). I would make sure your app port is configurable either through environment variables or command line options. Likewise make sure it can be shut down gracefully to release the port.
As for forever, there is no reason to install it globally, package it with the application and then its available at ./node_modules/.bin

Deleting posted content using $resource in AngularJS

I am new to AngularJS and am trying out a few things with posting and deleting content using $resource. I've got the posting working fine, but when I try to delete something that I've posted I get a 404 error.
DELETE http://localhost:3000/tasks?__v=0&_id=53c5ddcf2978af0000ccdc50&beginningDat…vacy=true&title=This+is+a+complete+task&website=http:%2F%2Fwww.hotmail.com 404 (Not Found)
I've been working on this for a few days now and I'm just not seeing what i am missing. I am using a MEAN stack. I've got mongoose, express, bodyParser, and cors as dependencies in my app.js and created my endpoints:
app.get('/tasks', api.getTask);
app.post('/tasks', api.postTask);
app.delete('/tasks/:_id', api.deleteTask);
Here is the code from my api.js which
exports.deleteTask = function(req, res){
var _id = req.params._id;
Task.remove({_id:_id}, function(err, task){
res.send(task + ' removed task successfully');
if(err){
res.send('Hey guys...he is still here.');
}
});
};
Here is my factory/service:
'use strict';
angular.module('achievementApp').factory('tasks', function($resource){
return $resource('http://localhost:3000/tasks/',{_id: '#_id'},{
get: {method:'GET', isArray: true},
add: {method:'POST'},
delete: {method: 'DELETE'}
});
});
And here is the code from the Ctrl:
$scope.taskList = tasks.get({});
$scope.removeTask = function(obj){
tasks.delete(obj);
var index = $scope.taskList.indexOf(obj);
console.log(index);
$scope.taskList.splice(index,1);
console.log('removeTask was called');
};
Any guidance on this would be greatly appreciated. I've tried just about everything I can to get it to work and have had no luck so far.
It looks like you have a mismatch between the angular code which is putting the _id in the query string and the express code which is looking for it as a route param, which looks in the path part of the URL. req.params comes from the path part before the ?. req.query comes from the query string part after the ?. It would be more conventional to use the path in terms of REST, so I suggest changing your angularjs code to have /tasks/:_id as the resource route.
Aside: Best to use relative paths in your browser JS and omit the protocol, host, and port. Otherwise your app won't work when you deploy it on the real web.

Node.js Express: BodyParser Syntax

Hi everyone i am new to node.js and express. i am just experimenting with various node.js code from various tutorials.
As per the official npm website correct syntax to use methodOverride is
// Be sure to place after the body parser if you want to accept the method
// override using a post parameter
app.use(express.bodyParser());
// Accepts a single argument, the name of the method override parameter,
// defaults to "_method"
app.use(require('express-method-override')('method_override_param_name'));
But when i used this, i got the following error
Error: Most middleware (like bodyParser) is no longer bundled with Express and
ust be installed separately. Please see https://github.com/senchalabs/connect#m
ddleware.
at Function.Object.defineProperty.get (E:\node_modules\npm\node_modules\exp
ess\lib\express.js:89:13)
As far as i researched app.use(express.bodyParser()) is deprecated. Express no longer includes the bodyParser middleware. So to my guess app.use(bodyParser()) is right and i altered my code like this
app.use(bodyParser());
app.use(require('express-method-override')('method_override_param_name'));
Below is my put functionality code
app.put('/user/:id', function(req, res){
console.log('Sha Put testing');
console.log(req.body);
//user.findByIdAndUpdate({email: req.params.id},
user.update({email: req.params.id},
{
email: req.body.email,
name: req.body.name,
age : req.body.age
},
function(err, docs){
if(err) res.json('Error here paiyaa -->' + err);
else
{
console.log(docs);
res.redirect('/user/'+req.body.email);
}
});
});
When i replace app.put with app.post it works fine. But my task is to achieve PUT functionality.As mentioned in express-method-override source, I have used hidden field with the name _method, which helps to override POST method, and facilitates PUT method.
My Edit form code is
<h1>Editing #{user.name}'s profile!</h1>
form(method="POST", action="/user/#{user._id}")
input(type="hidden", name="_method", value="PUT")
p Name:
input(type="text", name="name", value="#{user.name}")
p Age:
input(type="number", name="age", value="#{user.age}")
p
input(type="submit")
When i run the above code it throws below error while submitting the form
Cannot POST /user/test#gmail.com
Can some expert help me to fix this and understand bit clear please
You have a PUT route defined with app.put, but are trying to POST to it. The verbs need to match up, so either your request should be a PUT (makes sense for your user.update method) or change the route to app.post.
EDIT:
Looking at the source for express-method-override, your request body needs to have a _method: 'PUT' (as a default -- currently you are passing 'method_override_param_name' property on it in order for the middleware to override the POST verb.
If you are not already, you should also be including the body-parser middleware. npm install body-parser on the commandline or add it to your package.json and run npm install. var bodyParser = require('body-parser'); will then give the rest of your code what it needs to include the middleware.

Resources