Node JS GET API's not working with new data - node.js

I am using Node JS and MYSQL. When I add new data to my project, it writes to the database. Then when I want to GET this data with another API, it doesn't come. When I try again after about a minute, it comes on. However, right after I send a request via Swagger, data comes from the outside (Postman or Panel) on my request again.
My simple Controller.
exports.GetAll = (req, res, next) => {
ThisModel.GetAllSQL()
.then((response) => {
res.status(200).json(response[0]);
}).catch((error) => {
res.status(400).send();
console.log('Senaryo listesi çekilirken bir hata meydana geldi: ' + error);
})
}

.then((response) => {
res.status(200).json(response[0]);
})
Judging from the line above, it looks like you're getting a list/array of data, but only returning the first item in the list response[0].
Maybe this is what you're looking for:
.then((response) => {
res.status(200).json(response);
})

Related

Node GET by ID API

I have follow the instructions to create a NODE API here.
I'm trying to have a few endpoints with a NODE app to serve data to my React UI.
The database is mongodb where I have a collection for 'stores'.
I have 2 GET calls:
One to retrieve all stores
One to retrieve a store by ID
Node app.js:
app.get('/viewstores', (request, response) => {
storesCollection.find({}).toArray((error, result) => {
if (error) {
return response.status(500).send(error);
}
response.send(result);
});
});
app.get("/viewstores/:id", (request, response) => {
storesCollection.findOne({ "_id": new ObjectId(request.params.id) }, (error, result) => {
if(error) {
return response.status(500).send(error);
}
response.send(result);
});
});
I make my API calls from axios in React.
If I make a call to the first API to retrieve all stores, there no problem at all, but if I try to make the API call by ID, I still get all stores from the first API.
It seems that I am not able to target the GET by ID api.
React app
React.useEffect(() => {
axios.get('http://localhost:5000/viewstores', {
params: { _id: params.storesid}
})
.then(({data}) => {
console.log("DATA ==> ", data)
})
.catch(error => console.log("ERROR API GET ==> ", error))
}, [])
MongoDB store sample:
_id: ObjectId("12345")
businessname:"ABC"
businessaddress:"address abc 1"
Any idea why when I try to call the GET by ID I always get back the whole collection?
Thanks in advance.
Joe.
Assume params.storesid is 12345,
your current React code sends requests to http://localhost:5000/viewstores?_id=12345, and the route /viewstores is reached. To reach the /viewstores/:id route, the URL should be something likes http://localhost:5000/viewstores/12345 then Express will capture the 12345 part in the URL to request.params.id. You can try the code below:
React.useEffect(() => {
axios.get(`http://localhost:5000/viewstores/${params.storesid}`)
.then(({data}) => {
console.log("DATA ==> ", data)
})
.catch(error => console.log("ERROR API GET ==> ", error))
}, [])
You can read about Express route parameters in the official document.

Files not being sent in a multipart form when testing endpoint using Jest Supertest Formidable

I'm trying to test an endpoint that should receive a multipart/form-data. I'm sending a collection of images, which i want to process and save on the server or CDN. I'm using Jest, Express and Formidable.
Endpoint
router.post("/videos", async (req, res) => {
new formidable.IncomingForm().parse(req, (err, fields, files) => {
console.log('PARSE FORM');
if (err) {
console.error('Error', err);
throw err
}
console.log('Fields', fields);
console.log('Files', files);
for (const file of Object.entries(files)) {
console.log('FILE', file)
}
});
res.status(200).send('Created Video');
});
Test
describe("Video Endpoints", () => {
it('should create a new timelapse video', done => {
request
.post('/api/videos')
.field('file', 'some random value')
.attach('image', `${__dirname}/__mocks__/image.png`)
.then(res => {
console.log('THEN');
done();
})
});
});
When running the test it doesn't reach the formidable parse method.
If change my my attach method to this...
.attach('image', fs.readFileSync(`${__dirname}/__mocks__/xdebugcurlaccessingwpapi.png`))
It will reach the parse method but it sees the it as field and not a file.
If i make the same request but from my react app using fetch, it works perfectly fine.
What am i doing wrong? Been on this for a few days now lol.
Any help would be great.
Thanks.
I'm not entirely sure why but if you add
.set({connection: 'keep-alive'})
Then it works.
Final solution
request
.post('/api/videos')
.set({connection: 'keep-alive'})
.field('name', 'Richard')
.attach('image', mockImage)
.then(res => {
console.log('THEN');
done();
});
});
Would be good if someone has an understanding to why this is the case.
I think it might close the stream to image but can't be sure.

Client side can't fetch server response

The Problem
I deployed a create-react-app webapp to aws ec2. It's used to display data from a database and send data to it. I use ExpressJS, CORS and MySQL.
With the following code i fetch the corresponding URL and the server.js sends back the database content. Until here, everything works fine.
getBets = _ => {
fetch("http://ec2***.amazonaws.com
.then(response => response.json())
.then(response => this.setState({bets: response.data}))
.catch(err => console.error(err))
};
The problem begins when sending data to the database with the following code:
addBet = _ => {
const { bet } = this.state;
fetch(`http://ec2***.amazonaws.com/bets/add?name=${bet.person_name}&bet=${bet.time_bet}`)
.then(response => response.json())
.then(this.getBets)
.catch(err => console.error(err))
};
On click the addBet-function populates the db, but in chrome I following error:
GET http://ec2***.amazonaws.com/bets/add?name=Peter%20Pan5&bet=10:17%205 net::ERR_EMPTY_RESPONSE
and
TypeError: Failed to fetch
Regarding chrome dev-tools, the first error corresponds to the fetch in the addBet function and the second error to the catch part.
On the server side I've the following code for processing the fetch:
app.get("/bets/add", (req, res) => {
const {name, bet} = req.query;
const INSERT_BET = `INSERT INTO bets (name, bet, timestamp) VALUES("${name}", "${bet}", CURTIME())`;
connection.query(INSERT_BET, (err, res) => {
if (err) {
return res.send(err);
}
else {
return res.send("succesfully added your bet");
}
})
});
I want to mention, that the res paramter in the app.get part is unused. That tells me my IDE.
After a lot of hours digging deeper in the topics of expressJS and the fetch api, I guess, that the app.get part doesn't send a response to the server. But the fetch need some response.
My Question
How do I have to change the code in the app.get part to send a proper response back to the server?
AND
Am I right with my guess?
In MYSQL when you do an insert query you get back err,results and fields in the callback function like this:
connection.query('INSERT INTO posts SET ?', {title: 'test'}, function (error,
results, fields) {
if (error) throw error;
console.log(results.insertId);
});
You have used the parameter res for result and then you have used res.send() which now corresponds to that res parameter in the callback function and not the res object.Rewrite it like this:
app.get("/bets/add", (req, res) => {
const {name, bet} = req.query;
const INSERT_BET = `INSERT INTO bets (name, bet, timestamp) VALUES(?,?,?)`;
connection.query(INSERT_BET,[name,bet,CURTIME()] ,(err, result) => {
if (err) {
return res.send(err);
}
else {
return res.send("succesfully added your bet");
}
})
});
I have also used prepared statement in place of normal sql queries. These are used to prevent sql injections. I hope it will work now.

Reading response from MongoDB after updating the database

I am trying to read/use the response from mongo db after I create a new record in the db. I am using Node JS, Angular 2/4 and Ionic 3. I am successfully able to post the request, however, I am stuck at reading the response(I get the response in JSON) Screenshot of the response in my console
Now in the js code, I am trying to get the value of FirstName. How do I access it ?
This is my ts code.
CreateProfile(){
this.Loader("Creating Account");
this.params={
FirstName:this.createDetails.get('firstName').value,
LastName:this.createDetails.get('lastName').value,
City:this.createDetails.get('city').value,
Dob:this.createDetails.get('myDate').value.formatted, //this.userDob, //this.formPersonal.get('dob').value,
State:this.createDetails.get('state').value,
EmailID:this.createAccount.get('email').value,
Phone:this.createDetails.get('phone').value,
Gender:this.createDetails.get('gender').value,
Address:this.createDetails.get('address').value,
PinCode:this.createDetails.get('pincode').value,
Password:this.createAccount.get('password').value
}
this.NewProfile.createProfile(this.params).then(res=>{
console.log(res);
})
}
I am printing my response on the console.log(res) which you can see on the attached image, I am tyring to access the values
I have tried res[0].FirstName
I have tried res.FirstName
I have got errors both times.
This is code from my router/provider file
public createProfile(options){
return new Promise((resolve, reject) => {
this.http.post(this.localUrl, options)
.map(res => res.json())
.subscribe(res => {
resolve(res);
}, (err) => {
reject(err);
});
});
}
I have removed all other codes irrelevant to this question. I am guessing this would be a very trivial issue but not able to figure out what I am missing here
I got the solution, I just had to use an array like this (below code)
this.NewProfile.createProfile(this.params).then(res=>{
console.log(res['FirstName']);
})
Didn't realize it was this straightforward

Catch superagent request error before piping

I'm trying to pipe a file from service A trough service B into my Postman cliente. Service A builds an delivers a CSV file, and service B (nodejs) has to pipe into my client.
After researching a lot I have managed to successfully pipe the files into service B and then into Postman. Now I want to handle the ugly cases: what if the request token is invalid? What if I can't find the file?
As of this moment, I have found zero documentation or examples on how successfully handle errors while piping a request using superagent.
This is what I have so far
router.post("/csv", (req, res) => {
download_csv(req.get("Authorization"), req.body.ids)
.then((response) => {
res.sendFile(path.resolve(response));
})
.catch((err) => {
res.status(error.status).json(error.response.body);
})
});
function download_csv(token, ids) {
const stream = fs.createWriteStream("filters.csv")
let request = agent
.post(`${profiles}/api/documents/csv`)
.set("authorization", token)
.send({
ids: ids,
action: DOWNLOAD_CSV_PROFILES
})
request.on("response", res => {
// Maybe I can use abort to handle this thing, but can't figure out how!
// if (res.status !== 200) request.abort()
console.log(res.status)
})
request.on("abort", () => {
console.log("aborted")
return new Promise((resolve, reject) => {
resolve("request aborted")
})
})
request.pipe(stream)
return streamToPromise(stream);
}
function streamToPromise(stream) {
return new Promise((resolve, reject) => {
stream.on("error", (err) => {
console.log("error in error")
})
stream.on("finish", () => {
console.log("File saved")
resolve(stream.path);
});
});
}
This code handles the creation of the files correctly. When I fake the token or misspell the Authorization header, I get a correct 401 response, but a file gets written anyway with its contents being the authentication error.
Can anyway give me a hint on how to:
actually catch and manage the request when fails
in such case, how to escape the piping by going back to the express context and just returning a failed express request?
Many thanks!
If I understand you correctly, simply create the fs write stream in on('response') and make a small fix on the resultion.
function download_csv(token, ids) {
return new Promise((resolve, reject) => {
let request = agent
.post(`${profiles}/api/documents/csv`)
.set("authorization", token)
.send({
ids: ids,
action: DOWNLOAD_CSV_PROFILES
})
request.on("response", res => {
// Maybe I can use abort to handle this thing, but can't figure out how!
if (res.status === 200) {
res
.on("end", resolve)
.pipe(fs.createWriteStream("filters.csv"));
} else {
reject();
}
})
request.on("abort", reject);
});
}
I'm not sure what is the "request" you're using - but assuming it's actually the request npm module that will help.
Ideally, upload the file to a temporary directory and move it when the promise is resolved, delete on rejected. This way you'll solve the issue of partial downloads.
If you want to make any on-the-fly transforms, check out my "scramjet". It'll make everything easier with promises.

Resources