Put request req.body is empty - javascript

As all my requests are working fine, I have a problem with the put. req.body stays empty and then gives that error :
errmsg: "'$set' is empty. You must specify a field like so: {$set:
{: ...}}"
PUT :
router.put('/books/:name', (req, res, next) => {
const localdb = db.client.db(process.env.DB_NAME);
const collection = localdb.collection(process.env.COLL_BOOKS);
collection.replaceOne(
{ "name": req.params.name },
{ $set: req.body },
function (err) {
if (err) throw err
res.status(201).send(true);
});
App.js
const express = require('express'),
app = express();
os = require('os');
const bodyParser = require('body-parser');
const cors = require('cors');
const router = require('./router.js')
require('dotenv').config()
app.use(cors());
app.use(bodyParser.json());
app.use('/api/v1', router);
const port = (process.env.PORT || '3001');
let server = app.listen(port, os.hostname(), () => {
let host = server.address().address,
port = server.address().port;
console.log("Example app listening at http://%s:%s", host, port);
});
axios request :
updateItem = newBook => {
Axios.put(process.env.REACT_APP_API_PATH_BOOKS + `${newBook.name}`, newBook)
.then(res => {
this.setState({ newBook: res.data });
this.props.history.push('/admin');
})
.catch(err => console.log(err));
}
I don't understand what I am doing wrong

Make sure you don't have any middlware stripping or incorrectly parsing the body. For instance, you may have a JSON body parser, and not be sending JSON data with JSON application headers.
Can you give a bit of context, in code, for how you are making the put request and also the result of logging the req in a pastebin?

Related

access localhost with smartphone and get no response from the server

website works via localhost on pc
access with smartphone to localhost via ip too (I receive html, css and js for client)
when I click the button, a "hi" is also added but function "search()" is not executed
but when I enter the url http://localhost:3000/users I get the "hi1"
What do i have to do to make this work?
Client Side
const button = document.querySelector("button");
button.addEventListener("click", () => {
document.getElementById("imageDiv").innerHTML = "Hi";//this work
search();//this not work
});
async function search(){
await fetch("http://localhost:3000/users")
.then(response => response.json())
.then(response => {
var image;
image = JSON.parse(JSON.stringify(Object.assign({},response)));
document.getElementById("imageDiv").innerHTML = response;
})};
Server Side
const express = require('express');
const bodyParser = require('body-parser');
const path = require("path"); // window or mac
const cors = require('cors');
const app = express();
const port = 3000;
//var word = "";
//const router = express.Router();
// configure CORS to avoid CORS errors
app.use(cors());
// configure body parser so we can read req.body
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static('./client'));
app.get('/', (req, res) => {
res.sendFile("./index.html");
});
app.get("/users", (req, res) => {
datafiles = ["hi1"];
res.json(datafiles);
res.status(200);
});
app.listen(port, () => {
console.log(`Server listening on http://localhost:${port}`);
});

req.body is empty, why?

I want to send some data to my MongoDB database, but in router.post my req.body is empty, if I use stuff that I put in my send function in User(req.body) instead of req.body data will be send to my MongoDB database correctly.
This is my router that I use, router.get work fine, it return database tables correctly on /api page:
const router = require("express").Router();
const User = require("./model/models");
const parser = require("body-parser").json();
router.get("/", async (req, res) => {
const data = await User.find({});
res.json(data);
});
router.post("/",parser,async (req, res) => {
console.log('1')
console.log(req.body)
console.log('2')
parser.v
await User(req.body).save();
res.json({"msg": "ok"});
});
module.exports = router
This is my index.js file code:
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
const parser = require("body-parser").json();
var path = require('path');
app.use(express.urlencoded(true));
app.use(express.json());
app.use(parser);
app.use('/',require("./routes/routes"))
app.use(express.static(__dirname +'/public'))
app.use("/api", require('./data/api'))
app.listen(5000,function(){
console.log('server is alive')
})
This is function that what I use to send data:
const btn1 = document.getElementById('btnEnter')
let Login = "123"
btn1.addEventListener('click' ,e=>{
send({newsTxT : "someTextHere",newsZag:"someZag",author:"SomeAuthor"})
})
const send = async(body) => {
let res = await fetch("/api", {
method: "post",
header: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify(body)
});
let data = await res.json();
console.log(data)
}
The only weird thing I see is that you are using a json body-parser and also the express.json() both technically do the same, but body-parser is deprecated so it might be causing a bug.
Also you don't have to import it again in the routes, placing app.use(express.json()) at index.js will make it work for all endpoints/routes.
See how this refactor goes:
const router = require('express').Router()
const User = require('./model/models')
router.get('/', async (req, res) => {
const data = await User.find({})
res.json(data)
})
router.post('/', async (req, res) => {
console.log('1')
console.log(req.body)
console.log('2')
await User(req.body).save()
res.json({ 'msg': 'ok' })
})
module.exports = router
index.js
const express = require('express')
const app = express()
var path = require('path')
app.use(express.urlencoded(true))
app.use(express.json())
app.use('/', require('./routes/routes'))
app.use(express.static(__dirname + '/public'))
app.use('/api', require('./data/api'))
app.listen(5000, function () {
console.log('server is alive')
})
The following worked fine:
const express = require("express")
const app = express()
const router = express.Router()
router.use(express.json())
app.use(router)
router.post('/api/user', function(req, res) {
// ...
}
I see the difference may be using the: app.use(router)
Note that in the above code the statement:
router.use(express.json())
can be replaced with (using the body-parser):
const bodyParser = require('body-parser')
router.use(bodyParser.json())
This worked fine with express version 4.17.1, body-parser version 1.19.0 and NodeJS version 12.18.3

Having Issues with Writing Backend Code in Express and Connecting To React

I'm writing a code for creating a group within a website. And I'm using MongoDB as my database, but as a beginner, it's hard for me to understand the API that they provide. So basically, I'm having issues with connecting the backend to the frontend when I'm trying to create a group for my website. This is the backend code for create_group
router.post('/create_group', (req, res) => {
try {
const newGroup = Group.create(req.body);
res.status(201).json({
data: {
Groups:
newGroup
}
});
} catch (err) {
res.status(400).json({
status: 'fail',
message: err
});
}
//res.json(database.groups[database.groups.length-1]);
As you can see, I want to write a code that's appropriate for MongoDB that looks like the portion that I commented out. I want to return the object that I just saved so I can display that information in when I change the route. The frontend code looks like this:
onSubmitCreate = () => {
fetch('http://localhost:3000/groups/create_group', {
method: 'post',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: this.state.name,
description: this.state.description,
members: 1,
likes: 0
})
})
.then(response => response.json())
.then(group => {
if (group) {
//this.props.loadUser(user);
console.log('this is what Im working on' + group.name);
this.props.onCreateGroup(group);
}
});
}
In the frontend, as I make a request to post the information to the database, I want to read the response and work with that information. But when I console.log the group variable, I just get an empty object as a response and I don't know how to make it return the information that the user typed in. And in case you want to see what onCreateGroup fucntion looks like, here it is.
const onCreateGroup = (group) => {
setGroupInfo({
name: group.name,
description: group.description,
likes: 0,
members: 1
});
setRoute('group_page');
}
Please help me! Thank you in advance!
Edit: I was requested to post js file where I import express so I'm posting it here
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const cors = require('cors');
const bodyParser = require('body-parser');
const logger = require('morgan');
const mongoose = require('mongoose');
mongoose.connect("mongodb+srv://teamboogle:wMKsYJNhTfL89k9#cluster0.nhcrc.mongodb.net/TalkWithMe?retryWrites=true&w=majority", { useNewUrlParser: true });
const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');
const profileRouter = require('./routes/profile');
const postsRouter = require('./routes/posts');
const groupsRouter = require('./routes/groups');
const signinRouter = require('./routes/signin');
const registerRouter = require('./routes/signin');
var app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(cors());
app.use(bodyParser.json());
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/profile', profileRouter);
app.use('/posts', postsRouter);
app.use('/groups', groupsRouter);
app.use('/signin', signinRouter);
app.use('/register', registerRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'))
db.once('open', function(){
console.log('Connection Secured');
})
module.exports = app;
You are not saving the object in MongoDB properly, and you also need to return the object that you saved in Group collection as well.
Also, since you are returning data.Groups.group, you need to read that in the response as well
Please try this:
router.post('/create_group', async (req, res) => {
try {
const newGroup = new Group(req.body);
let group = await newGroup.save()
res.status(201).json({
data: {
Groups:
group//return the saved object
}
});
} catch (err) {
res.status(400).json({
status: 'fail',
message: err
});
}
}
In frontend code
onSubmitCreate = () => {
fetch(...)
.then(response => response.json())
.then(data => {
// read data.Groups.group from response
let group = data.Groups.group
if (group) {
//this.props.loadUser(user);
console.log('this is what Im working on' + group.name);
this.props.onCreateGroup(group);
}
});
}

unable to send post request using socket.io

here i am sending data from socket client to socket server and after receiving the request it has to send to node api
**the issue is im getting null ** on calling the socket server
below is my code
Socket Client
socket.connect();
socket.emit("posreq",JSON.stringify({ "title": "data"}));
Socket Server
var http = require('http'),
io = require('socket.io'), // for npm, otherwise use require('./path/to/socket.io')
request = require('request'),
cors = require('cors'),
server = http.createServer(function (req, res) {
// your normal server code
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.end('Hello world');
});
server.listen(4000);
// socket.io
var socket = io.listen(server);
socket.on('connection', function (client) {
// new client is here!
client.on('posreq', function (postdata) {
request.post("http://localhost:3000/book", {
body: postdata
}, function (res) {
console.log(res);
client.send("post req called",postdata);
});
});
client.on('disconnect', function () {
console.log('connection closed');
});
});
Node api
const express = require('express')
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express()
const port = 3000
let books = [{
"title": "Eloquent JavaScript, Second Edition",
}];
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.post('/book', (req, res) => {
const book = req.body;
// output the book to the console for debugging
console.log(book);
// books.push(book);
res.json('Book is added to the database');
});
I tried but unable to understand the issue
Note : How can i convert the Socket server to express js code
As far I understand you are willing to use express instead of HTTP and that will solve your problem. And in the below code, I have used express as well as HTTP. Try code below
const express=require("express")
const app=express()
const server=require("http").createServer(app)
const socket=require("socket.io")(server)
server.listen(4000,()=>console.log(`Listening to port 4000`))
socket.on('connection', function (client) {
client.on('posreq', function (postdata) {
request.post("http://localhost:3000/book", {
body: postdata
}, function (res) {
console.log(res);
client.send("post req called",postdata);
});
});
client.on('disconnect', function () {
console.log('connection closed');
});
});
May be you need few modification,
Request is depricated so better to use axios or other alternative.
const express = require("express")
const bodyParser = require("body-parser")
const axios = require('axios')
const app = express()
const httpServer = require("http").createServer(app)
const socket = require("socket.io")(server)
app.use(bodyParser.json({ limit: '16mb' }));
app.use(bodyParser.urlencoded({ limit: '16mb', extended: true, parameterLimit: 50000 }));
app.get('/', (req,res)=> res.send("Hello world"));
socket.on('connection', function (socket) {
socket.on('posreq', async (body) => {
try {
const { data } = await axios.post("http://localhost:3000/book", { body })
socket.send("post req called", data);
} catch (error) {
socket.send("post req error", error);
}
});
socket.on('disconnect', function () {
console.log('connection closed');
});
});
httpServer.listen(3000, () => console.log(`Spinning 3000`))

SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data on React app

I have a React app that uses express in the backend. I try to get from my db a list of messages through a fetch API call.
The code in the Frontend:
App.js
getMessages = () => {
fetch('/api/mess')
.then(res => res.json())
.then(res => {
var Messages = res.map(r => r.messages);
this.setState({ Messages });
});
};
The code in the backend:
api/mess.js
var express = require('express');
var Mess = require('../queries/mess');
var router = express.Router();
router.get('/', (req, res) => {
Mess.retrieveAll((err, messages) => {
if (err)
return res.json(err);
return res.json(messages);
})
});
router.post('/', (req, res) => {
var message = req.body.message;
Mess.insert(message, (err, result) => {
if (err)
return res.json(err);
return res.json(result);
});
});
module.exports = router;
queries/mess.js
const db = require('../database');
class Mess {
static retrieveAll(callback) {
db.query('SELECT * FROM mess;', (err, res) => {
if (err.error)
return callback(err);
callback(res);
});
}
static insert(mess, callback) {
db.query('INSERT INTO mess (messages) VALUES ($1)', [mess], (err, res) => {
if (err.error)
return callback(err);
callback(res);
});
}
}
module.exports = Mess;
index.js
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
var db = require('./database');
const ENV = process.env.NODE_ENV;
const PORT = process.env.PORT || 3011;
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use('/api/mess', require('./api/mess'));
app.use('/api/roles', require('./api/roles'));
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}...`);
});
module.exports = app;
I get this error on my Frontend:
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
I have tried and changed every response and request to use either JSON.parse or .json and I get the same message no matter what.
When I use my browser and go to the api channel I get a correctly formatted JSON with the contents of the db.
Did I miss something?
EDIT:
The stack trace is super minimal:
When I try:
getMessages = () => {
fetch('/api/mess')
.then(res => console.log(res));
};
I get this object:
The problem is that the backend is at PORT 3011 and the api call is made to PORT 3000 from the frontend.
I need to have a proxy to point from the forntend to the backend port.
I need to add inside client/package.json (Frontend) this line:
"proxy": "http://localhost/3011"

Categories