I'm trying to do a get request method in Vue and Express to get data based on my v-model.
Below is my code that tries to send data to express.
getResult() {
axios
.get(
`${process.env.VUE_APP_API}/hospita/result/` +
{
hosp_name: "SAMPLE"
}
)
.then(res => console.log(res.data))
.catch(err => console.log(err));
}
and here is my get request method that receives the data coming from vuejs
router.get('/result/', (req, res) => {
const sql = "SELECT * FROM \
ND_HOSP WHERE hosp_ptype = 'h' AND hosp_name LIKE ?";
console.log(req.body)
myDB.query(sql, ['%' + req.body.hosp_name + '%'], (err, result) => {
if (err) {
console.log(err)
} else {
try {
res.send(result);
/* console.log(result) */
} catch (err) {
res.send(err)
}
}
})
})
but it gives me error and says
http://localhost:9002/hospita/result/[object%20Object]
In your getResult() let's to change method to post and + to , for passing your data in body. You can look at this code below:
getResult() {
axios
.post( // <= change method to post
`${process.env.VUE_APP_API}/hospita/result/`, // change `+` with `,`
{
hosp_name: "SAMPLE"
}
)
.then(res => console.log(res.data))
.catch(err => console.log(err));
}
After that, don't forget to change your router method from get to post. You can look at this code below:
// change method `get` to `post`
router.post('/result/', (req, res) => {
const sql = "SELECT * FROM \
ND_HOSP WHERE hosp_ptype = 'h' AND hosp_name LIKE ?";
console.log(req.body)
myDB.query(sql, ['%' + req.body.hosp_name + '%'], (err, result) => {
if (err) {
res.send(err)
} else {
res.send(result);
}
})
})
Make sure, because we're use the req.body, so, don't forget to add body parser in your server.js or app.js. It's will looks like this code below:
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
I hope it can help you.
problem is here: res.send(result);
result is not containing json data, it is containing any other object or blank object like {}.
so first of all try to see what is inside the result using console.log().
most of the time for the such cases two functions are very useful.
JSON.stringify(object);
JSON.parse(strobj);
Related
I have created middleware to validate fields in body, here is how it looks like:
Front-end route:
router.post('/s-i', async (req, res) => {
try {
const { data } = await api.post('/sign-in', req.body)
res.cookie("_rt", data._rt, { httpOnly: true, secure: false })
delete data._rt
return res.json(data)
} catch (e) {
// Here is error
return res.status(e.response.status).json(e.response.data)
}
});
Route (back-end):
router.post('/sign-in', v(['email', 'password', 'twoFa', 'phone']), wrapAsync(userController.signIn));
Middleware:
exports.v = fields => {
return (req, res, next) => {
fields.forEach(field => {
if (req.body[field]) {
const result = require(`./validators/${field}`)(req.body[field])
if (!result)
return res.status(400).json({ message: 'bad-request', status: 400 })
}
})
next()
}
}
In the place where comment is placed I can see this error, actually, everything works find, and if there is wrong field in body front will receive 400 status code, but in back-end terminal I still have this error and can't get why.
The problem is I still keep getting this ERR_HTTP_HEADERS_SENT error. I know the reason of this problem - for example - if you are trying do res.send({}) twice, but I don't really see the reason of problem in this case.
The return res.status(400)... statement returns only from the inner function fields.forEach(field => {...}), but you must return from the middleware function, otherwise the next() will invoke subsequent middlewares after the .json output, leading to the observed error.
You can achieve this by replacing fields.forEach(field => {...}) with
for (var field of fields) {
if (req.body[field]) {
const result = require(`./validators/${field}`)(req.body[field])
if (!result)
return res.status(400).json({ message: 'bad-request', status: 400 })
}
}
While trying to fetch data from my express backend and MySQL database, with my react frontend using axios, it fails to set the fetched data using useState
my frontend function looks like this
const searchUser = () => {
Axios.post("http://localhost:3001/searchUser", {
username: username,
}).then((response) => {
if (response.data) {
setResult(response.data);
}
});
};
and my backend function looks like this
const searchUser = (req, res) => {
const keyword = req.body.username;
db.query(
"SELECT id,username FROM users WHERE username like ?",
"%" + keyword + "%",
(err, result) => {
if (err) {
res.json({ message: err });
console.log(err);
} else {
console.log(result);
res.json({ result });
}
}
);
};
I tried many methods while saving the data with the useState hook, I appreciate any help
While using Promises and then instead of async / await make sure to catch the errors if your fetch fails.
Unless you share with us the whole component that contains the searchUser function and how you defined the state i cannot pin point you on the error.
What i suggest you to do is adding a catch to your fetch by doing the following:
const searchUser = () => {
Axios.post("http://localhost:3001/searchUser", {
username: username,
}).then((response) => {
if (response.data) {
setResult(response.data);
}
}).catch((error) => {
console.error(error);
});
};
If any abnormalities has happened in your request the catch will tell you! Don't underestimate it's power.
Another path you can look into is console logging your output in front end searchUser function just before setting it in the state.
I did solve the problem, just by replacing res.json({ result }); to res.json(result); in the last line in my backend function
I have an object i need to parse to React.
I'm trying to get the "rows" object (in the node function) over to a React State.
The 2 piece of code below are on different pages!
The other issue is
GET http://localhost:3000/new net::ERR_CONNECTION_REFUSED
I am currently running these both locally
React http://localhost:3001/
Node - http://localhost:3000/
There have been SIMILAR questions to this but I can't find an answer with both issues!
Thanks
router.get("/new", (req, res) => {
let parentList = sql.fetchAllParents(function(err, rows) {
res.setHeader("Access-Control-Allow-Origin", "http://localhost:3001");
if (err) throw err;
res.render('new', {parents: rows});
});
});
componentDidMount() {
fetch(`http://localhost:3000/new`).then(response => {
console.log(response)
return response.json();
}).then(data => {
// Work with JSON data here
console.log(data,'data');
}).catch(err => {
// Do something for an error here
console.log("Error Reading data " + err);
});
}
Send response from node "new" api. Like this:
router.get("/new", (req, res) => {
......
......
res.send({status:200,parents:data})
});
I am using NodeJs and MongoDb as a back-end service.In my collection i have several documents having fields named _id and Name but Node is returning only first document and showing error in console.I want to fetch only Name field of a document.
Error:
Here is my code:
var express = require('express');
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.post('/offers',(req, res) => {
MongoClient.connect(url, (err, db) => {
if(err) throw err;
var dbo = db.db('Tiffino_db');
dbo.collection("Offers")
.find({},{ projection: { _id: 0 } })
.toArray((err, result) => {
if (err) {
console.log("Error:", +err);
}
else {
for(var i = 0;i<result.length;i++){
res.send(result[i].Name);
}
db.close();
}
});
});
});
Please let me know what I did wrong in above code.
THANKS
It looks like you're trying to send multiple responses in a loop using Response.Send() as a response is only sent once.
This won't work, you'll need to create an array of names, and then use Response.Send() to do this once.
Using res.send(result.map(r => r.name)) would probably work
You should aggregate the results into a variable and then call res.send() only once:
let resultString;
for(var i = 0;i<result.length;i++){
resultString += result[i].Name + '\n';
}
res.send(resultString);
If you want to stream the results, you can use res.write() and when done call res.end()
You can not use res.send() multiple time in a for loop, try somthing like this
var data=[];
for(var i = 0;i<result.length;i++){
data.push(result[i].Name);
}
res.send(data);
app.post('/offers',(req, res) => {
MongoClient.connect(url, (err, db) => {
if(err) throw err;
var dbo = db.db('Tiffino_db');
dbo.collection("Offers")
.find({},{ projection: { _id: 0 } })
.toArray((err, results) => {
if (err) {
console.log("Error:", +err);
}
else {
response = results.map(result => result.Name);
//res.send(response);
// in json format
res.json(response);
db.close();
}
});
});
});
...
...
else {
output = result.map(offer => offer.name);
res.send({output});
db.close();
}
This should work as you can only send response once on a single response object and you are calling that for results.length times.
I'm pretty sure you're not supposed to be calling res.send(...) multiple times. Since you're calling it inside a loop, it will send the first document and fail in the next as expected.
Lets say I have multiple places where I call response.send(someData). Now I want to create a single global interceptor where I catch all .send methods and make some changes to someData. Is there any way in express.js? (hooks, listeners, interceptors, ...)?
You can define a middleware as below (taken and modified from this answer)
function modifyResponseBody(req, res, next) {
var oldSend = res.send;
res.send = function(data){
// arguments[0] (or `data`) contains the response body
arguments[0] = "modified : " + arguments[0];
oldSend.apply(res, arguments);
}
next();
}
app.use(modifyResponseBody);
for those finding on google, based off the top answer:
app.use((req, res, next) => {
const oldSend = res.send
res.send = function(data) {
console.log(data) // do something with the data
res.send = oldSend // set function back to avoid the 'double-send'
return res.send(data) // just call as normal with data
}
next()
})
Yes this is possible. There are two ways to do this, one is to use a library that provides the interception, with the ability to run it based on a specific condition:
https://www.npmjs.com/package/express-interceptor
The other option is to just create your own middleware (for express) as follows:
function modify(req, res, next){
res.body = "this is the modified/new response";
next();
}
express.use(modify);
Just want to provide a practical usage example with intercepting res.json.
When we're writing express server, we might send the status and message in every response according to the situation like below.
app.post('/test', (req, res) => {
res.json({status: 1, message: "some_error", otherData: "nothing"})
})
But, what if I don't want to write the status and message in every time? I could add new function to build a template response body to send the data when using res.json.
const messageMap = {
0: "success",
1: "some_error"
}
app.use((req, res, next) => {
const originJson = res.json
res.json = (status, jsonData) => {
const fixedResponse = {
status,
message: messageMap[status]
}
originJson.call(res, {...jsonData, ...fixedResponse})
}
next()
})
Then I just need to use below function.
app.get("/test", (req, res) => {
res.json(1, {otherData: 1})
})
You can even use builder pattern to do this.
app.use((req, res) => {
res.buildFixedResponse = function (status) {
const fixedResponse = {
status,
message: messageMap[status]
}
res.json = function (jsonData) {
originJson.call(this, {...jsonData, ...fixedResponse})
}
return this
}
})
Then trigger function like below.
app.get("/test", (req, res) => {
res.buildFixedResponse(1).json({otherData: 1})
})
For my case, I had to use a middleware with typicode/json-server and be able to get a different response object than just a blunt javascript array.
While the typicode/json-server response was something like:
[
{
...
}
]
After applying the middleware:
module.exports = (req, res, next) => {
const oldSend = res.send;
res.send = (data) => {
const oldData = JSON.parse(data);
// we want to change the response only if a blunt array is sent
// also, we do this for the old sake of not sending json arrays
if(Object.prototype.toString.call(oldData) === '[object Array]') {
data = {
data: oldData
};
}
res.send = oldSend;
return res.send(data);
};
next();
}
The response looks as follows:
{
data: [
{
...
}
]
}
You can simply do it using NODEJS and Express, say you are calling an API and want to send modify the data before sending response back.
router.get('/id', (req,res) => {
... //your code here filling DATA
let testData = {
"C1": "Data1",
"C2": "Data2",
"yourdata": DATA
};
res.send(testData);
});