Simple get request with node.js and express - node.js

I have tried everything and can't figure out what i am doing wrong. I have no problem posting data from the client to the server but the other way around i can't get it to work.
The only response i get in my client is ReadableByteStream {}.
This is my code on the client:
export function getAllQuestionnairesAction(){
return (dispatch, getState) => {
dispatch(getAllQuestionnairesRequest());
return fetch(API_ENDPOINT_QUESTIONNAIRE)
.then(res => {
if (res.ok) {
console.log(res.body)
return dispatch(getAllQuestionnairesSuccess(res.body));
} else {
throw new Error("Oops! Something went wrong");
}
})
.catch(ex => {
return dispatch(getAllQuestionnairesFailure());
});
};
}
This is my code on the server:
exports.all = function(req, res) {
var allQuestionnaires = [];
Questionnaire.find({}).exec(function(err, questionnaires) {
if(!err) {
console.log(questionnaires)
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ a: 1 }));
//res.json(questionnaires)
}else {
console.log('Error in first query');
res.status(400).send(err);
}
});
}

I'm doing some guesswork here, since I'm not sure what flavor of fetch you are currently using, but I'll take a stab at it based on the standard implementation of fetch.
The response inside the resolution of fetch typically does not have a directly readable .body. See here for some straight forward examples.
Try this:
export function getAllQuestionnairesAction(){
return (dispatch, getState) => {
dispatch(getAllQuestionnairesRequest());
return fetch(API_ENDPOINT_QUESTIONNAIRE)
.then(res => {
if (res.ok) {
return res.json();
} else {
throw new Error("Oops! Something went wrong");
}
})
.then(json => {
console.log(json); // response body here
return dispatch(getAllQuestionnairesSuccess(json));
})
.catch(ex => {
return dispatch(getAllQuestionnairesFailure());
});
};
}

Related

React - delete request come with error code 404

I've an issue while i'm trying to delete a driver from mySQL db.
Calling my function and passing mapped id (it's working):
<button id="deleteRent" onClick={DeleteVehicles.bind(vehicle.id)}>Delete</button>
Here is my react code:
const DeleteVehicles = (CarId) => {
Axios.delete(`http://localhost:3001/vehicleDelete/${CarId}`)
.then((response) => {
if (response) {
console.log(response)
alert("Sikeres Törlés")
navigate("/admin");
}
else {
console.log("törlési hiba")
}
})
}
and here is my node express request:
app.delete('/vehicleDelete/:CarId'), async (req, res) => {
db.query("DELETE FROM products WHERE id = ?", req.params.CarId,
(err, result) => {
console.log(err)
console.log(result)
if (result) {
res.send(result);
}
})
}
any idea?
axios should be lowercased:
axios.delete(`http://localhost:3001/vehicleDelete/${CarId}`)
Be careful with the closing parentheses on the express code:
app.delete('/vehicleDelete/:CarId', async (req, res) => {
db.query("DELETE FROM products WHERE id = ?", req.params.CarId, (err, result) => {
if (err) return res.status(500).send('Error')
res.status(200).send(result);
})
})
You should run this:
app.delete('/vehicleDelete/:CarId'), (req, res) => {
// make sure your are getting CarId that exists
// and then you delete it
db.query(`DELETE FROM products WHERE id = ${req.params.CarId}`,
(err, result) => {
console.log(err)
console.log(result)
if (result) {
res.send(result);
}
})
}
Also, you don't need to add async as your not using await for the query. The result gives you an object that might look like this:
{
fieldCount: 0,
affectedRows: 1,
insertId: 0,
serverStatus: 34,
warningCount: 0,
message: '',
protocol41: true,
changedRows: 0
}
Now, when you say you receive the 404 status code, it means that you don't have the route on which the request is made. So, http://localhost:3001/vehicleDelete/${CarId} you need to register the route properly at the server.
You should add the catch blocks with Promises, it is recommended practice.
const DeleteVehicles = (CarId) => {
Axios.delete(`http://localhost:3001/vehicleDelete/${CarId}`)
.then((response) => {
if (response) {
console.log(response)
alert("Sikeres Törlés")
navigate("/admin");
}
else {
console.log("törlési hiba")
}
}).catch(console.log);
}

How to catch an empty reply from an API {}

I'm currently using Node.js to fetch an API data and converting it into my own Express.js API server to send my own data (The 2 APIs I'm using changes the structure sometime and I have some users that need to keep the same structure).
So here is the code I'm using
app.get('/app/account/:accountid', function (req, res) {
return fetch('https://server1.com/api/account/' + req.params.accountid)
.then(function (res) {
var contentType = res.headers.get("content-type");
if (contentType && contentType.includes("application/json")) {
apiServer = 'server1';
return res.json();
} else {
apiServer = 'server2';
throw "server1 did not reply properly";
}
}).then(server1Reconstruct).then(function (json) {
res.setHeader('Content-Type', 'application/json');
return res.send(json);
}).catch(function (err) {
console.log(err);
}).then(function () {
if (apiServer == 'server2') {
server2.fetchAccount({
accountID: [Number(req.params.accountid)],
language: "eng_us"
})
.then(server2Reconstruct)
.then(function (json) {
res.setHeader('Content-Type', 'application/json');
return res.send(json);
}).catch(function (err) {
console.log(err);
});
}
});
})
To quickly explain the code: I call server1 through a normal Fetch this answer might be {} which is where I have a problem. If the accountid doesn't exist the server returns an JSON response with no errors to grab...
What should I do to be able to catch it... And If I catch it switch to server 2.
(Don't be too confused about server2 call as it's another package).
If I understand your problem correctly, you should follow those steps :
fetch the initial API
call the .json() method on the result - which returns a promise
deal with the json response in the first .then(json => ...), and here check if the result is {} then call server2, else call server1
BTW, your code looks very messy with all those then and catch, I recommend putting some stuff into functions, and using async/await if you can.
Here is some pseudo-code sample that you could use :
function server2Call() {
return server2.fetchAccount({
accountID: [Number(req.params.accountid)],
language: 'eng_us'
})
.then(server2Reconstruct)
.then(function (json) {
res.setHeader('Content-Type', 'application/json');
return res.send(json);
}).catch(function (err) {
console.log(err);
});
}
app.get('/app/account/:accountid', function (req, res) {
return fetch('https://server1.com/api/account/' + req.params.accountid)
.then(res => {
var contentType = res.headers.get('content-type');
if (contentType && contentType.includes('application/json')) {
return res.json();
} else {
server2Call()
}
})
.then(json => {
res.setHeader('Content-Type', 'application/json');
if (json is {}) return server2Call()
else return res.send(json);
}).catch(function (err) {
console.log(err);
})
});

NodeJS two queries in one route

I need to display Invitation and Comments in the same rendered file (show.hbs)
I have this code here, and it's working fine, except I cannot achieve that comment's would also display. I would really appreciate any help.
I'm not getting any errors with this code.
app.get('/invitation/:id', (req, res) => {
let id = req.params.id;
if(!ObjectID.isValid(id)){
return res.status(404).send();
}
Comment.find({inviteId: id}).then((comment) => {
if(!comment){
return res.status(404).send();
}
res.render('show.hbs', {comment});
}, (e) => {
res.status(404).send();
});
Invitation.findById(id).then((invitation) => {
if(!invitation){
return res.status(404).send();
}
res.render('show.hbs', {invitation});
}, (e) => {
res.status(404).send();
});
}, (e) => {
console.log('Unable to find invitation', e);
});
You can do something like this,
Invitation.findById(id).then((invitation) => {
if (!invitation) {
return res.status(404).send();
}
Comment.find({ inviteId: id }).then((comment) => {
if (!comment) {
return res.status(404).send();
}
res.render('show.hbs', { comment, invitation});
}, (e) => {
res.status(404).send();
});
}, (e) => {
res.status(404).send();
});
and render it with both invitation and comment
Tnx to #vibhor1997a but this is much prettier
try {
let invitation = await Invitation.findById(id).then((invitation) => {
if (!invitation) {
return res.status(404).send();
}
let comments = await Comment.find({ inviteId: id })
if (!comments) {
return res.status(404).send();
}
return res.render('show.hbs', { comments, invitation});
} catch (e) {
return res.status(500).send();
}
You didn't paste your error message, but I'm pretty sure it's something like Error: Can't set headers after they are sent to the client.
Just nest your queries or use await https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await.

Adding req object to Kue job

Been hunting the internet trying to find an answer to why the following doesn't work.
I am trying to pass in the req object when I add the job so that I have access to it when the job is processed.
But the process is never executed when the whole req object is passed to job.data. Yet I can pass parts of the req object.
What I'm trying to do maybe anti-pattern and a big no no. But, I am trying to understand why it won't work. It seems strange that it just continues without any error.
Below is an example, hopefully it is clear.
My kue is abstracted into a separate file, and initialised onto app.locals.Q as follows:
// Q.js
class Q {
constructor(options) {
this.q = kue.createQueue(options)
}
addJob = (name, data) => {
return Queue.create({
queue_job: name,
queue_route: data.route,
queue_user: data.user,
queue_added: new Date(),
})
.then(response => {
this.q.create(name, {
id: response.get('queue_id'),
route: data.route,
request: data.request
})
.save();
return Promise.resolve(response);
})
.catch(error => {
return Promise.reject(error);
});
processJob = (name, work, options = {}) => {
const {concurrency} = options;
this.q.process(name, concurrency || 1, (job, done) => {
const {data: {id, route, request}} = job;
Queue.update({
queue_running: true
}, {
where: {
queue_id: id
}
})
.then(() => {
if (process.env.NODE_ENV !== 'production') {
console.log(`running job ${id} from ${route}`);
}
return new Promise((resolve, reject) => {
return work(resolve, reject, request);
});
})
.then(results => {
return Queue.update({
queue_running: false,
queue_completed: new Date(),
queue_results_path: results || null
}, {
where: {
queue_id: job.data.id
}
});
})
.then(() => {
if (process.env.NODE_ENV !== 'production') {
console.log(`completed job ${id} from ${route}`);
}
done();
})
.catch((error) => {
if (process.env.NODE_ENV !== 'production') {
console.log(`failed job ${id} from ${route}`);
console.log(error);
}
Queue.update({
queue_running: false,
queue_error: `${error}`
}, {
where: {
queue_id: id
}
})
.then(() => {
done(error);
})
.catch(err => {
console.error(err);
done(err);
});
});
});
};
};
// example route
queue = (req, res) => {
const {locals: {Q}} = req.app;
Q.addJob('foo', {
route: req.path,
user: req.user.get('username'),
request: req
})
.then(queue_id => {
Q.processJob('foo', (resolve, reject, request) => {
console.log(request)
resolve('complete')
})
res.json({sucess: true})
})
}
redis can't serialize the req object.
kue simply silently fails.

Server sends success even if didn't find anything

I send data from my input fields to my api:
$.ajax({
url: '/api/login',
type: 'GET',
dataType: 'json',
ContentType: 'application/json',
data: {formData},
success: (data) => {
console.log('SUCCESS')
console.log(data)
this.setState({
isInProcess: false
})
},
error: (jqXHR) => {
console.log(jqXHR)
console.log('ERROR')
this.setState({isInProcess: false})
}
})
on my server-side I have a function to see if I have required user in db:
async function findUser(data) {
try {
const user = await User.findOne({email: data.email,
password: data.password})
console.log('User was found')
return { user }
} catch (err) {
console.log('error', err)
throw err
}
}
which will be executed here:
app.get('/api/login', async (req, res) => {
const data = req.query
try {
const foundUserData = await findUser(data.formData)
return res.json(foundUserData)
} catch (err) {
return res.status(400).json(err)
}
})
It works fine, but if a user wasn't found in db i sends success anyway. Why?
await findUser(data.formData) won't throw error, return either null or user object. You may check something following
app.get('/api/login', async (req, res) => {
const data = req.query
try {
const foundUserData = await findUser(data.formData)
if(foundUserData && foundUserData.user) {
return res.json(foundUserData)
} else {
return res.status(400).json({message: 'User not found'});
}
} catch (err) {
return res.status(500).json(err)
}
})
It sends success because none of your queries error'ed, just because it didn't find anything does not mean that the query failed because it obviously succeeded in finding out if what ever you're looking for exists or not.
To send an error in case of not found you need to check if response is empty in which case you want to send error
When no user is find you get a null value. You may try to put more logic on your success parameter with that for example:
success: function (data) {
if(!!data && data != null) {
alert('Success');
} else {
alert('No data');
}
}

Resources