I'm trying to escape form input for a simple demo express app, and I'm getting a result I don't understand.
When I execute this route:
/* Update a toy */
app.post('/toys/:id', [
body().escape()
], (req, res) => {
console.log("Update: ");
console.log(req.body);
toyController.update(req, res);
});
I get this output:
Update:
[object Object]
It looks to me as if the request body is getting destroyed.
If I remove the middleware,
/* Update a toy */
app.post('/toys/:id', (req, res) => {
console.log("Update: ");
console.log(req.body);
toyController.update(req, res);
});
I get the expected result:
Update:
{
toy: {
name: 'Playstation 4',
description: 'A gaming console',
manufacturer: 'Sony',
price: '400'
},
commit: 'Update Toy'
}
Update: If I call body('toy') instead of body(), I get the following result:
{ toy: '[object Object]', commit: 'Update Toy' }
So, it appears that the problem lies in the fact that that body is a nested object.
How can I apply the validation/sanitization to body.toy instead of all of body?
Is there a way that I can directly call the escape code an apply it to a specific string, instead of using the entire middleware setup?
You need to use body().escape() in a correct way. Please refer below an example.
const express = require('express');
const { body } = require('express-
validator');
const app = express();
app.use(express.json());
app.post('/comment', [
body('email')
.isEmail()
.normalizeEmail(),
body('text')
.not().isEmpty()
.trim()
.escape(),
body('notifyOnReply').toBoolean()
], (req, res) => {
// Handle the request somehow
});
Above example contains the right way to use express validator.In the example above, we are validating email and text fields, so we may take advantage of the same chain to apply some sanitization, like e-mail normalization (normalizeEmail) and trimming (trim)/HTML escaping (escape).
The notifyOnReply field isn't validated, but it can still make use of the same check function to convert it to a JavaScript boolean.
Sorry the indentation is not good, I am posting the answer from mobile.
Since you modified the question. You can use schema validation by express- validator.
https://express-validator.github.io/docs/schema-validation.html
Related
I am submitting a form with an image. Using the below code.
router.post("/", upload.upload('image').single('categoryLogo'), categoryRules.categoryCreationRules(), validate, categoryController.createCategory);
It is working fine, but is some validation comes then still image is saving in disk.
so what I tried is :
router.post("/", categoryRules.categoryCreationRules(), validate,upload.upload('image').single('categoryLogo'), categoryController.createCategory);
But in this express validator getting blank body so it throws validation error very time.
What should I do for it, I search on google but I did not found any helpful info I am new in the node.
Rules code:
const categoryCreationRules = () => {
return [
check('name')
.isLength({ min: 1 })
.trim()
.withMessage("Category name is required."),
check('name').custom((name)=>{
return CategoryModel.findOne({name: name}).collation({locale:'en',strength: 2})
.then(category=>{
if(category){
return Promise.reject(category.name+" category already exsist.");
}
})
}),
check('name')
.isLength({max: 100})
.trim()
.withMessage("Category name should not exceed more then 100 characters."),
check('description')
.isLength({max: 255})
.trim()
.withMessage("Category description should not exceed more then 255 characters.")
];
}
In theory, running categoryCreationRules and validate middlewares before multer would be enough. Therefore, you would only need a verification in the request body and if it contains any errors, you just return a bad request response, not letting the request pass to the next middleware (in this case the multer).
A simple example what i'm talking about: (Just to let it clear, the below code won't work)
router.post("/", categoryRules.categoryCreationRules(), validate, upload.upload('image').single('categoryLogo'), categoryController.createCategory);
const validator = (req, res, next) => {
try {
validationResult(req).throw();
// Continue to next middleware, in this case, multer.
next();
} catch (errors) {
// return bad request
res.status(400).send(errors);
}
};
this won´t work because your req.body will be undefined, as you are sending the data as a multipart/form-data (generally used to upload files). And in this case, errors will always be true.
But with multer this will not happen - you will be able to access body fields like description and name and then do the validation code.
This occurs because multer, internally, parses the multipart/form-data request to body with a library called busboy, and with this you can access fields through req.body.
Because of that, i think the best approach here is call multer middleware before your validations middlewares:
router.post("/", upload.upload('image').single('categoryLogo'), categoryRules.categoryCreationRules(), validate, categoryController.createCategory);
And after that, if the validation has an error, you delete the file created from multer and return a bad request response, something like that:
const fs = require("fs");
const validator = (req, res, next) => {
try {
validationResult(req).throw();
// continue to next middleware
next();
} catch (errors) {
fs.unlink(req.file.path, (err) => {
if (err) {multipart/form-data
/* HANLDE ERROR */
}
console.log(`successfully deleted ${req.file.path}`);
});
// return bad request
res.status(400).send(errors);
}
};
You can get more info about this in the below links:
node-js-with-express-bodyparser-unable-to-obtain-form-data-from-post-request
req-body-undefined-multipart
html-multipart-form-data-error-in-req-body-using-node-express
To upload an image , you have set the enctype of form to multipart/form-data . But if you use multer later, you don't have the form data parsed, hence probaby giving undefined.
Please check multiparty , an npm module
https://www.npmjs.com/package/multiparty
It also parses other fields along with file uploads and validation might be easy to set.
I am building a backend service to convert YAML to JSON. However, it returns ["object Object"].
Postman post request in text: name: wf1
Code:
import { safeLoad } from 'js-yaml'
app.post('/,
function (req, res) {
res.send(JSON.stringify(safeLoad(req.body)))
}
)
Return ["object Object"]
I expect it return JSON format of name: wf1.
You need to make sure the body is actually parsed as raw text if you're intending to send text (i.e. Content-Type: text/plain) in your request. Using the text-function from body-parser should fix this issue:
app.use(bodyParser.text())
app.post('/', (req, res) => {
res.send(JSON.stringify(safeLoad(req.body)));
})
Note that if you're intending to send actual json back to the client you need to change this to:
app.post('/', (req, res) => {
res.json(safeLoad(req.body));
})
First of all, according to js-yaml, safeLoad function only accept String as input type but req.body should return as a object. Maybe point to the particular key can work for you.
I have a collection like
{
id:"david123",
friends[{id:joe321, lname"woo", fname"joe"}]
}
i want to add new elements into friends
i currently have this, but it does not seem to be working
app.post('/users/:uid/friends', function(req, res){
var userId = req.params.uid;
Friend.update({'_id': userId},
{$push: {Friends: req.body.friend}},
{ upsert : true },
function(err, result){
if (err){
console.log(err);
} else {
res.status(200).json(result);
}
})
});
i defined my schema like this
var FriendSchema = new mongoose.Schema({
_id: String,
Friends: [{
_id: String,
fname: String,
lname: String
}]
});
when i make a request i send
{ friend: '{userId:"john123",lname"smoth",fname"john"}',
userId: 'userId123' } and im getting
[TypeError: Cannot use 'in' operator to search for '_id' in {userId:"john123",lname"smoth",fname"john"}]
The sentence "it does not seem to be working" tells us nothing, really. Is there any error printed? Is there bad data inserted? No data? What is the response to the HTTP request? Those are the most important questions but since no relevant info is provided I can only give you some hints:
Make sure that the connection to Mongo is successful
Make sure that you're connecting to the database that you think you are
Make sure you use body parser with correct encoding if needed
Make sure to use $addToSet instead of $push to avoid duplicates
Make sure to return a response on error and not only on success
Make sure you send a request with POST method with JSON content type
Make sure that you send the data in the request body
Make sure that the JSON in your request contains the friend property
Make sure you have some request logging
For (3) see: https://github.com/expressjs/body-parser#bodyparserjsonoptions
For (4) see: https://docs.mongodb.com/manual/reference/operator/update/addToSet/
You didn't say anything about a framework that you use and you did not your question with a framework tag but your code suggests that you may be using Express. If that's the case then to use req.body in the request handlers you need to use a correct body parser middleware:
npm install body-parser --save
and in your code - at the beginning:
const bodyParser = require('body-parser');
and somewhere after you have app but before app.post(...); you need:
app.use(bodyParser.json());
if you want to have the request body parsed as JSON so you could use req.body and req.body.friend in your handler.
And use some basic logging in your request handler:
app.post('/users/:uid/friends', (req, res) => {
// start with:
console.log('Request body:' JSON.stringify(req.body));
// the rest of the logic ...
});
to see what is actually passed in the response and that it is correctly deserialized by the appropriate body parser.
How do I write a get handler for the following URL with node.js?
http://localhost:3000/auth?code=xxxxxxx
The following code did not work
app.get('/auth', function (req,res) {
});
It's not working because it doesn't do anything. You need to send a response:
app.get('/auth', function (req,res) {
res.send('Hi it worked. Code: ' + req.query.code);
});
Another way to do it would be like this:
app.get('/auth/:code', function (req,res) {
res.send('Hi it worked. Code: ' + req.params.code);
});
and the URL would simply be http://localhost:3000/auth/xxxxxxx
Please note that, some client sides should accept a certain response type.
For instance, you should send a JSON object as a response.
So, rather than just responding a string, it is better if you send a JSON object as:
app.get('/auth', function (req,res) {
res.send({ 'response' : 'Hi it worked.', 'code': req.query.code });
});
I was exploring developing in Node.JS and found ExpressJS and RailwayJS (based on Express) which are frameworks for Node. The templating engine used Jade/EJS appears to be more for HTML. How might I generate JSON, eg. when I develop an API
Express and Railway both extend off the HTTP module in node and both provide a "response" object as the second argument of the route/middleware handler's callback. This argument's name is usually shortened to res to save a few keystrokes.
To easily send an object as a JSON message, Express exposes the following method:
res.json({ some: "object literal" });
Examples:
app.use(function (req, res, next) {
res.json({ some: "object literal" });
});
// -- OR -- //
app.get('/', function (req, res, next) {
res.json({ some: "object literal" });
});
Check out the docs at expressjs.com and the github source is well documented as well
You just create normal JavaScript objects, for example:
var x = {
test: 1,
embedded: {
attr1: 'attr',
attr2: false
}
};
and
JSON.stringify(x);
turns it into JSON string. Note that x may contain functions which will be omitted. Also JSON.stringify returns x.toJSON() if .toJSON() is available.