Nodejs/Mongoose fetch individual data with routes. [MongoDB] - node.js

Im trying to find the cleartext for a certain hash with making a get including the hash in the link.
This code only fetches the data from the given id
router.get('/:id', async (req, res) => {
try {
const md5 = await MD5.findById(req.params.id)
res.json(md5);
} catch (err){
res.status(500).json({ message: err.message })
}
})
GET Request
http://localhost:3000/md5/5ecd8e223ec4a031bccb299b
Output
{"cleartext":"softking","hash":"1e055704bb253ab362b3563902e88fe8","_id":"5ecd8e223ec4a031bccb299b"}
My goal is to make a get request with a hash to find the cleartext instead of requesting with a id. Sorry that I can't explain better, Im a newbie in this.

First you need to pass the hash as a parameter to your get request. Then, you can use find method instead of findById provided by mongoose
router.get('/:hash', async (req, res) => {
try {
const md5 = await MD5.find({hash:req.params.hash});
res.json(md5);
} catch (err){
res.status(500).json({ message: err.message });
}
});

Related

How do I manage GET random and GET by ID calls in REST API?

I want to get a random character from MongoDB, but my call keeps getting used in another GET method.
// Get Specific Character by ID
router.get('/:char_id', async (req, res, next) => {
try {
const character = await Character.find({ char_id: req.params.char_id });
if (character.length == 0) return res.status(404).json({ message: 'No characters found with ID: ' + req.params.char_id });
else { res.status(200).json(character) };
} catch (err) {
res.status(500).json({ message: err.message });
}
});
// Get Random Character
router.get('/random', async (req, res, next) => {
try {
const characters = await Character.find();
if (characters.length == 0) return res.status(404).json({ message: 'No characters found in the database. Something must have went wrong.' });
else {
const random = Math.floor(Math.random() * characters.length);
res.status(200).json(characters[random]);
};
} catch (err) {
res.status(500).json({ message: err.message });
}
});
When I call /characters/random, I get this error because first GET method above tries to pass word random to find character by ID (If I'm not wrong).
"message": "Cast to Number failed for value "random" (type string) at path "char_id" for model "Character""
How do I avoid this?
You can just put the second route above the first route. That works in similar cases for me.
A route like this:
router.get('/:char_id', ...)
is a wildcard route. It matches EVERYTHING at its level. So, it will match your intended ID, but it will also match /random. Thus, it "eats" your /random request and that request never gets to your actual handler for /random.
A quick fix here is to make sure the wildcard route is LAST on the router. That way, all the other routes get first dibs at the incoming request and only the left-over requests that didn't match some other handler will go to your wildcard route.
This is the desired order of your route declarations:
router.get('/random', async (req, res, next) => { ... });
// put this one last on the router
router.get('/:char_id', async (req, res, next) => { ... });
Even better would be to not use a wildcard route (that matches everything) at all, but rather define a regex for your char_id that would ONLY match your intended id strings and would not match other route paths.

I cant get a response from a POST request with an array in the body, Using NodeJS / Axios and Postman

This is a course quiz and this is the most basic information I need in order to create a React app. But while the endpoint URL is correct, the page "/products" returns a "400" error when I try to request the product list. The instructions I'm given are:
Obtain a list of products with
Route: /products
Body: Array
method: POST
{
"product-codes": [
"98798729",
"84876871",
"29879879",
]
}
My index.js
...
app.post(`/products`, async (req, res) => {
try {
const response = await axios.post(`${apiURL}/products`);
// console.log(response.data);
res.status(200).json(response.data);
} catch (error) {
res.status(400).json({ message: error.message });
}
});
in Postman
I use http://localhost:4000/products
and pass a Body / Raw /JSON:
{
"product-codes": [
"98798729",
"84876871",
"29879879",
]
}
But I can't get in! I am not seeing something obvious because this is the entry point to a very long and complex quiz. Thanks
What I see from the code is a recursive long call.
app.post(`/products`, async (req, res) => {
try {
const response = await axios.post(`${apiURL}/products`); // calling the same end point
// console.log(response.data);
res.status(200).json(response.data);
} catch (error) {
res.status(400).json({ message: error.message });
}
});
You should do something like this:
app.post(`/products`, async (req, res) => {
// do your logic
// when you pass body from postman on this endpoint
// you will receive the body here and save it to DB
// or do the manipulation and then send back the response
res.status(200).json(req.body.data);
});
I highly recommend you to first follow through some tutorials to understand how API works and how to create simple API using Node.js.

Sign up and log in, Express, React, Node, Psql

I am trying to create signup and Login for the first time with express and react using PostgreSQL. My post works just fine. A user can be added to the database so I jumped into handling duplicates.
I am using the findUserByEmail function to find my email and then, in my routes, create the user if it does not exist.
I tried everything and still is giving me problems. I manage to get it working by just returning the query, without a response, which I don't think is right:
const findUserByEmail = (req, response) => {
return pool.query("SELECT * FROM users WHERE email = $1", [req.body.email])
};
Although, I need the response to handle the errors.
The way that I found more common and is how I am trying is:
const findUserByEmail = (req, response) => {
pool.query("SELECT * FROM users WHERE email = $1", [req.body.email]),
(error, results) => {
if (error) {
throw error;
}
response.json(results.rows);
};
};
And when I call it here:
app.post("/signup/user", (req, res, next) => {
queries
.findUserByEmail(req, res)
.then(user => {
if (user.rows.length > 0) {
res.status(400).send("this email is already in use");
} else {
queries.createUser(req.body, res);
}
})
.catch(err => {
console.log(err);
res.status(500).send("Something went wrong");
});
});
But the error is:
Cannot read property 'then' of undefined
If anybody can give me a hand cause I've been 2/3 weeks just for the authentication.
I'll leave my repo if anybody wants to have a look, is a bit messy though.
https://github.com/jaitone/CRUD-in-JS
Thank you!
if you are using pg as part of your project. then:
const findUserByEmail = (req, response) => { // send just email instead
return pool.query("SELECT * FROM users WHERE email = $1", [req.body.email])
};
Is completely legal and beautiful. The library creates a promise and returns it.
I manage to get it working by just returning the query
It is not returning the query, it is returning the mechanism to run the query in a promise wrapper(to be run in the future). So when you do .then it will actually execute and return the result. BUT
If you want to do it manually:
In the findUserByEmail you are not returning a Promise, instead you are just ending the request chain by saying res.json(which in turn means you are returning undefined).
You can create a Promise wrapper or use util.promisfy to make the pool.query a promise.
const findUserByEmail = (req, response) => { // send just email instead
return new Promise((resolve, reject)=>{
pool.query("SELECT * FROM users WHERE email = $1", [req.body.email]),
(error, results) => {
if (error) {
reject(error);
}
resolve(results.rows);
};
});
};
Note, sending the email instead of whole req and res objects is a good idea.

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.

Noob - API getting stuck in a simple GET (express,node)

In trying to build my first express API, I am encountering many problems. I am following some simple guide on youtube, and his code works (FOR HIM). When I try it with Postman, I simply get nothing, but it appears to be in some kind of loop (because I handle the errors)
I have checked that my route is ok, and tried experimenting with next() (which seems like I don't need it just yet)
Player is my model made with Mongoose
app.get("/players/:id", (req, res) => {
const id = req.params.id;
Player.findById(id)
.exec()
.then(doc => {
console.log("From database", doc);
if (doc) {
res.status(200).json(doc);
} else {
res
.status(404)
.json({ message: "No valid entry found for provided ID" });
}
})
.catch(err => {
console.log(err);
res.status(500).json({ error: err });
});
});
So when trying a GET in Postman on:
http://localhost:3000/players/5cf66338f00c424494316eb2
I get a loading screen, and after some time "There was an error connecting to...".
Any help/tips/solution/insights are appreciated!
If your repo is up-to-date, then you are not connecting your app with your database.
Add the following code in your app replacing the database with your own database:
mongoose.connect('mongodb://localhost:27017/database', {useNewUrlParser: true});

Resources