I have a problem validating on update (express) - javascript

I'm trying to create a validator that will display an error message when a user tries to update a column that doesn't exist in the database schema. I'm using PostgreSQL. When I send a request with the correct allowed updates it returns an error: 'Invalid updates' What am I missing?
const updateQuestion = async (req, res) => {
const updates = Object.keys(req.body)
const allowedUpdates = ['title', 'text, questionCateg']
const isValidOperation = updates.every((update) => allowedUpdates.includes(update))
if (!isValidOperation) {
return res.status(400).send({
error: 'Invalid updates'
})
}
try {
const {
id
} = req.params;
const {
title,
text,
questionCateg
} = req.body
const updateQuestion = await pool.query("UPDATE Questions SET title = $1, text = $2, questionCateg = $3 WHERE id =$4",
[title, text, questionCateg, id]);
console.log(updateQuestion)
res.json('Question updated')
} catch (e) {
res.status(400).send()
}
}
Route:
router.patch('/questions/:id', updateQuestion)
Thanks in advance!

What do you see when you console.log(req.body) ? you should concentrate on that updates array.
You can use body-parser in your app.js or express.json() middleware
This way you can succesfully receive your items that you are sending to your backend.
You can send the updates in post request body with the key updates. Then you can parse it like req.body.updates (updates is an array)
You can use body parser like this
app.use(bodyParser.urlencoded({
extended: true
}));
or app.use(express.json())
you can see further information in this post express.json() and express.urlencoded()

Related

Backend post request only reads as "undefined" JS

I am pretty new to JS so please go easy on me.
Im trying to increment a value in a JSON file in my JS backend application. Whenever I increment the associated value by the key, it creates a new section "undefined"
Here is the entire application:
const { response } = require("express");
const express = require("express");
const fs = require("fs").promises;
const path = require("path");
const app = express();
const dataFile = path.join(__dirname, "data.json");
//support POSTing form data wuth url encoded
app.use(express.json());
app.get("/poll", async (req, res) =>{
//data is now the js object of the Json data json
let data = JSON.parse(await fs.readFile(dataFile, "utf-8"));
const totalVotes = Object.values(data).reduce((total, n) => total +=n, 0);
data = Object.entries(data).map(([label, votes]) => {
return{
label,
percentage: (((100 * votes) / totalVotes) || 0).toFixed(0) // or with 0 in the even that you divide by zero
}
});
res.json(data);
});
app.use(express.urlencoded({ extended: true}));
app.post("/poll", async (req, res) => {
const data = JSON.parse(await fs.readFile(dataFile, "utf-8"));
data[req.body.add]++;
await fs.writeFile(dataFile, JSON.stringify(data));
res.json(data);
});
app.listen(3000, () => console.log("Server is running ..."));
Here is my JSON file before I POST
{
"JavaScript":0,
"TypScript":10,
"Both":3}
Here is a picture of my POST request in Insomnia:
Here is my JSON file after a Post Requests
{
"JavaScript": 0,
"TypScript": 10,
"Both": 3,
"undefined": null
}
Here is is after a second POST request:
{
"JavaScript": 0,
"TypScript": 10,
"Both": 3,
"undefined": 1
}
I know it might be something very simple, but I am very inexperienced so any help would be greatly appreciated!
I tried including some additional middleware to enable bodyParsing as I saw in other posts but that did not fix the issue.
I also tried
console.logging(req.body)
,but that only printed "undefined".
EDIT:
I found the problem, I wasn't sending the information in Insomnia correctly, I need to click the form type and either format a JSON input or select the "Form URL Encoded"" Option. Otherwise it doesn't recognize the format.
Thank you for your help!
I tried your code in my device, it works fine on my device which means you are not properly sending post request.
And there is a bug in your logic of adding name , in which you increment the add property of data object but that property is not a number but a null so the number does not increments. Here is a simple fix...
app.post("/poll", async (req, res) => {
const data = JSON.parse(await fs.readFile(dataFile, "utf-8"));
let {add} = req.body;
if(data[add] === 0 || data[add]) data[add]++;
else data[add] = 0;
await fs.writeFile(dataFile, JSON.stringify(data));
res.json(data);
});
If req.body printed "undefined", req.body.add will also be equal to "undefined".
This is causing the error. I haven't used Insomnia but when you send your POST request your "body" needs to be something like this:
{
"add": "variableName"
}

Having issues with app.post, results in Cannot Get /

I'm trying to create a sign-up page where users can enter information, however, I'm having issues with "app.post" properly working. This is what I have so far:
const express = require("express");
const db = require("./dbConnectExec.js")
const app = express();
app.use(express.json());
app.listen(5000, () => {
console.log('App is running on port 5000');
});
app.get("/hi", (req,res) => {
res.send("Hello world.");
});
app.get("/", (req,res) => {
res.send("API is running.");
});
// app.post();
// app.put();
app.post("/customers", async(req, res) => {
// res.send("/contacts called");
// console.log("request body", req.body)
let nameFirst = req.body.nameFirst;
let nameLast = req.body.nameLast;
let email = req.body.email;
let password = req.body.password;
let emailCheckQuery = `
SELECT customer_email
FROM Customer
WHERE customer_email = '${email}'`;
let existingUser = await db.executeQuery(emailCheckQuery);
console.log("existing user", existingUser);
if(existingUser[0]){return res.status(409).send("duplicate email")};
})
When I attempt to add a user through Postman, for example:
{"nameFirst": "Robert",
"nameLast": "Redford",
"email": "rob#mail.com",
"password": "asdfasdf"}
I end up with "Cannot GET /customers"
You have no GET handler for /customers only a POST handler
In postman you can change your request from a GET to a POST request. Once you do it should hit this route endpoint.
note:
"GET is used for viewing something, without changing it, while POST is used for changing something. For example, a search page should use GET to get data while a form that changes your password should use POST . Essentially GET is used to retrieve remote data, and POST is used to insert/update remote data."

Using express-formidable to get multipart data , but it makes simple post requests with request body run forever

app.js
const express = require('express')
const app = express()
const app = express()
const PORT = process.env.SERVER_PORT || 8080
app.use(express.json())
app.use(express.urlencoded({
extended : true
}))
app.use(formidableMiddleware());
app.listen(PORT, () => {
console.log(`The application is up and running on ${PORT}`)
})
controller.js
This contains the controller that takes base64 encoded image in formdata and that can be accessed with filename property (This is one controller which is working fine with formidable)
const uploadProfilePic = async (req, res) => {
let strArr = req.fields.filename.split(',')
let buffer = new Buffer(strArr[1], 'base64')
let filename =
Date.now().toString() + '' + strArr[0].split('/')[1].split(';')[0]
try {
req.user.profile = buffer
req.user.filename = filename
await req.user.save()
return res.status(200).json(
customMessage(true, {
message: 'Successfully uploaded',
}),
)
} catch (error) {
return res.status(500).status(internalServerError)
}
}
controller2.js This controller is not working properly, it does not even run when we use express-formidable and the post request route to which this controller is binded to, runs forever, but if we pass no request body then it runs perfectly or if we comment out:
//app.use(express-formidable);
//In app.js
then it runs properly but then controller.js doesnt run.
const updateUserData = async (req, res) => {
try {
const {_id, email, name, username, bio, code, platform, languages } = req.body
if (username === undefined || code === undefined || !platform || !languages)
return res
.status(400)
.json(customMessage(false, 'Please Satisy Validations'))
let user = req.user
let user1 = await UserModel.findById(_id)
user1.username = username;
user1.code = code;
user1.bio = bio;
user1.platform = platform;
user1.languages = languages;
if (!user) return res.status(500).json(internalServerError())
else {
await user1.save()
console.log
return res
.status(200)
.json(customMessage(true, `user with ${email} updated`))
}
} catch (error) {
console.log(error)
return res.status(500).json(internalServerError())
}
}
Okay I found a way to send requests through the multipart/form data and the application/json without breaking any thing. I actually spent 2 hours trying to figure out what happened and how to solve the problem. I discovered that the package "express-formidable" is no longer being maintained and has been closed down. Then I also found another package which of course solved the problem just about now "express-formidable-v2" which I believe is the continuation of the former package.
Check this https://github.com/Abderrahman-byte/express-formidable-v2 out, It is a fork of "express-formidable" package
Now you have access to your {req.fields} and {req.body}

Post request body returning undefined

I'm making a post request using axios and passing in a body like so:
export const uploadFeatured = (userId, uploadInfo) => async dispatch => {
////console.log("uploading", uploadInfo.mediaName, uploadInfo.video, uploadInfo.description);
const res = await axios.post(domain + '/api/uploadFeatured',
{mediaName: uploadInfo.mediaName,
video: uploadInfo.video,
description: uploadInfo.description});
console.log("response to upload", res)
}
However, at the server, I'm getting an undefined when accessing req.body.
app.post("/api/uploadFeatured", async (req, res) => {
try {
//////// req.body returning undefined.
console.log("upload featured is ", req.body)
const data = {name:"Name"}
const newFeatured = new Featured(data).save();
const client = algoliasearch('YD', '055b10');
const index = client.initIndex('Humboi');
index.saveObjects([data], {
autoGenerateObjectIDIfNotExist: true
}).then(({ objectIDs }) => {
console.log(objectIDs);
});
console.log("new featured is ", newFeatured);
} catch (e) {
console.log("error ", e)
}
});
What am I doing that's causing the body to be undefined in the node.js server rather than to be the map that's passed in axios?
Please install body-parser add following code in your js file after const path:
npm install body-parser
const bodyParser = require('body-parser')
app.use(bodyParser);
The bodyParser object exposes various factories to create middlewares. All middlewares will populate the req.body property with the parsed body when the Content-Type request header matches the type option, or an empty object ({}) if there was no body to parse, the Content-Type was not matched, or an error occurred.

Sending state for an Axios POST and data not showing in req.body

I'm using React and want to make a POST request using Axios. I'm trying to send form data to my Node backend.
I am trying to send an object in the POST request which is the state holding all of the user's inputs to a form.
React
const [formDetails, setFormDetails] = useState({})
const handleFormChange = (evt) => setFormDetails({ ...formDetails, [evt.target.name]: evt.target.value })
const sendInvoice = async (formDetails) => {
const response = await axios.post('/api/new_invoice', formDetails)
console.log(response)
}
Node route
module.exports = (app) => {
// Create a new invoice
app.post('/api/new_invoice', async (req, res) => {
console.log('making a new invoice...')
try {
console.log(req.body)
res.send(req.body)
} catch (err) {
console.log(err)
res.status(400)
res.send({ error: err })
return
}
})
}
This is what I get back:
When I look at the req.body for the response it is an empty object even though I can see that state is there when sending the form.
I also tried hardcoding an object and that will show the data on the req.body.
For example if I change the request to
const response = await axios.post('/api/new_invoice', {formData: 'this is form data'})
Then I am able to see formData: 'this is form data' in the req.body
You need to stringify the formData, In your sendInvoice function,
Also can you share the sample request body from postman of you have tested API there
let body= JSON.stringify(formData)
const config = {
headers: {
'Content-Type': 'application/JSON'
}
};
const res = await axios.post('/api/v1/new_invoice', body, config);
To handle an incoming JSON object from HTTP POST Request, you need to write the following code -
var express = require('express');
var app=express();
app.use(express.urlencoded()); // To parse URL-encoded bodies
app.use(express.json()); //To parse JSON bodies
// Note: (*applicable for Express 4.16+ )

Categories