Delete user endpoint using Fetch - javascript

I am building a user website, where the admin should be able to delete users.
My project is build using Azure SQL database.
I have in my controllers file, come up with an endpoint deleteUser
deleteUser
const deleteUser = (req, res) => {
sql.connect(config, function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
const { id } = req.query
request.query(
`DELETE FROM users where User_ID = '${id}'`,
function (err, recordset) {
if (err) {
console.log(err);
} else if (!id) {
res.json("Please provide an ID")
} else {
res.json(`User with ID: ${id} has been deleted!`)
}
}
);
});
};
I am then trying to make a call to this endpoint using fetch and EJS.
My code in EJS script tag
<script>
document.getElementById('deleteUserBtn').addEventListener('submit', (e) => {
e.preventDefault();
fetch('http://localhost:3000/deleteUser', {
method:'DELETE',
headers: {
"Content-Type": "application/json",
},
body: null
})
.then((response) => console.log(response))
.catch((e) => {
console.log(e)
})
})
</script>
I console log the response, so the route must be good, but it seems as it doesn't parse the ID into the fetch. What is the right way to approach this?
Thanks in advance!
Solution
I have come up with follow solution - which is not the best, but works.
document.getElementById('deleteUserBtn').addEventListener('submit', (e) => {
e.preventDefault();
// delete user using fetch
const id = document.getElementById('userId').textContent
fetch(`http://localhost:3000/deleteUser?id=${id}`, {
method:'DELETE',
headers: {
"Content-Type": "application/json",
},
body: null
})
.then((response) => console.log(response))
.catch((e) => {
console.log(e)
})
})
Thanks for the contribution!

Should the id not be in the URL of the fetch request? You are asking for the id from the request params, so it should probably be appended to the path like
const id = wherever your id comes from;
fetch('http://localhost:3000/deleteUser?id=${id}...'
You'll need to get the user's id in your button method as well, but would need more of your code to see where that comes from.

Usually using an ID for deletion is best approach
fetch('http://localhost:3000/deleteUser/:id...'
However, you can pass id in anyway in body, params, query or even headers)

Related

POST method to express server returning 404 [duplicate]

This question already has an answer here:
Express routes parameters
(1 answer)
Closed last month.
I'm trying to send a POST to my server, in order to edit a user's details. I've made sure it's sending to the right URL, however get a 404 response. GET requests work fine, however my POST doesn't seem to get through for whatever reason. I've been searching for solutions for a while, with no luck hence posting here!
user.js (server side)
userRoutes.route('/user/update/:id').post(function (req, response) {
let db_connect = dbo.getDb("preview");
let myquery = { _id: ObjectId(req.params.id) };
let newValues = {
$set: {
name: req.body.name,
user_name: req.body.user_name
},
};
db_connect
.collection("users")
.updateOne(myquery, newValues, function (err, res) {
if (err) throw err;
console.log('user updated');
response.json(res);
})
});
middleware
export const updateUser = async (id, userDetails) => {
const endpoint = `${serverIp}/user/update/?id=${id}`;
try {
const response = await fetch(endpoint, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(userDetails)
})
const result = await response.json();
return result;
} catch (error) {
console.log(error)
}
}
and a simple function to handle submitting
function handleSave() {
const newUserDetails = {
name: accountHolder,
user_name: accountUsername
};
updateUser(userId, newUserDetails);
}
Under networking in dev tools I can see the URL is indeed correct, so I can't see why this isn't working
chrome dev tools
Any help would be greatly appreciate it!
I've tried sending a basic response (i.e. a string instead of object), changing the endpoint, and more all to no avail
It seems like you are passing the id as a query param and not as part of the path
const endpoint = `${serverIp}/user/update/?id=${id}`;
^
What I can see from first glance is that in server-side you are using request parameter for id, but in the client you're sending id as a request query

How do I use a Get query?

Hello I created a form allowing me to choose which database table I want to observe. I then want to make a query based on the selected data but it seems that the format or my way of doing it does not seem good.
Here is my fetch function:
temp_select: 'temperature'
async exportData(){
const data_select = encodeURIComponent(this.temp_select);
const url = `http://192.168.1.51:3000/api/v1/export/${data_select}`;
fetch(url)
.then(res => res.text())
.then((result) => {
console.log(typeof(data_select));
const data = JSON.parse(result);
console.log(data);
})
.catch((error) => {
console.log(error)
});
},
and here is my query function
async function exportDatabase(req, res){
const data_selected = req.params.data_select;
return db.any('SELECT $1 FROM tag_7z8eq73', [data_selected])
.then(rows => {
res.json(rows)
})
.catch(error => {
console.log(error)
});
}
the database is loaded but here is what I observe
It works correctly in this form:
async function exportDatabase(req, res){
return db.any('SELECT temperature FROM tag_7z8eq73')
.then(rows => {
res.json(rows)
})
.catch(error => {
console.log(error)
}); }
I'm working with node.js and vue.js
Can someone enlighten me?
edit : #Quentin Thank you for your answer you help me understand how the GET request works. Here is my problem solved :
fetch function :
async exportData(){
const data_select = encodeURIComponent(this.temp_select);
const url = `http://192.168.1.51:3000/api/v1/export/${data_select}`;
fetch(url)
.then(res => res.text())
.then((result) => {
console.log(typeof(data_select));
const data = JSON.parse(result);
console.log(data);
})
.catch((error) => {
console.log(error)
});
},
Query function:
async function exportDatabase(req, res){
const data_selected = req.params.data_select;
return db.any('SELECT ' + data_selected + ' FROM tag_7z8eq73')
.then(rows => {
res.json(rows)
})
.catch(error => {
console.log(error)
}); }
my route :
router.get('/export/:data_select', db.exportDatabase);
method: 'GET',
You are making a GET request
headers: {
'Content-Type': 'application/json',
},
This claims that the request body is JSON.
GET requests cannot have a request body, so this cannot be true.
(Technically they can, but really shouldn't, but fetch won't let you give a GET request a body).
Remove this header.
params: JSON.stringify({
data_select: this.temp_select,
}),
fetch does not have a params option, so this is nonsense. Remove it.
async function exportDatabase(req, res){
return db.any('SELECT $1 FROM tag_7z8eq73', [req.params.data_select])
Assuming you are using Express, look at the definition of params:
This property is an object containing properties mapped to the named route “parameters”. For example, if you have the route /user/:name, then the “name” property is available as req.params.name. This object defaults to {}.
Which means you need to define data_select when you define the route:
app.get('/api/v1/export/:data_select', exportData);
And then put the value in the URL when you make the request:
const data_select = encodeURIComponent(this.temp_select);
const url = `http://192.168.1.51:3000/api/v1/export/${data_select}`;
fetch(url).then(...);

Unable to get the required redirect_uri in react-facebook-login

I'm trying to implement the Facebook OAuth in my express/NodeJS app using authorization code flow. I'm using react-facebook-login node module to fetch the authorization code. In my react app, I could get the authorization code successfully. But in server side, I can't request the access token from the Facebook API as I'm getting an error message "redirect_uri is not identical to the one you used in the OAuth dialog request"
Code in my react app,
facebookLogin = async (signedRequest) => {
return fetch('/api/auth/facebook', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ signedRequest }),
}).then((res) => {
if (res.ok) {
return res.json();
} else {
return Promise.reject(res);
}
});
};
responseFacebook = async (response) => {
try {
if (response['signedRequest']) {
const userProfile = await this.facebookLogin(response['signedRequest']);
console.log(userProfile);
} else {
throw new Error(response.error);
}
} catch (err) {
console.log(err);
}
};
render() {
<FacebookLogin
appId={process.env.FACEBOOK_CLIENT_ID}
fields="name,email"
responseType="code"
redirectUri="http://localhost:3000/"
callback={this.responseFacebook}
/>
In my app.js
const facebookOAuth = require('./config/facebookOAuth');
// facebook oauth route
app.post("/api/auth/facebook", async (req, res) => {
try {
const signedRequest = req.body.signedRequest;
const profile = await facebookOAuth.getProfile(signedRequest);
console.log(profile);
res.send({ profile });
} catch (err) {
console.log(err);
res.status(401).send();
}
});
facebookOAuth.js look like this
const fetch = require('node-fetch');
const getData = async (userId, accessToken) => {
const userData = await fetch(`https://graph.facebook.com/${userId}?fields=name,email&access_token=${accessToken}`, {
method: 'GET'
}).then((res) => {
return res.json();
}).then((userData) => {
return userData;
});
return userData;
};
exports.getProfile = async (signedRequest) => {
const decodedSignedRequest = JSON.parse(Buffer.from((signedRequest.split(".")[1]), 'base64').toString());
const profile = await fetch(`https://graph.facebook.com/oauth/access_token?client_id=${process.env.FACEBOOK_CLIENT_ID}&redirect_uri=${encodeURIComponent('http://localhost:3000/')}&client_secret=${process.env.FACEBOOK_CLIENT_SECRET}&code=${decodedSignedRequest.code}`, {
method: 'GET'
}).then((res) => {
return res.json();
}).then((token) => {
console.log(token);
const userData = getData(decodedSignedRequest.user_id, token.access_token);
return userData;
}).catch((err) => {
console.log(err);
return err;
});
return profile;
}
What I'm getting is this error
"error": {
message: 'Error validating verification code. Please make sure your redirect_uri is identical to the one you used in the OAuth dialog request',
type: 'OAuthException',
code: 100,
error_subcode: 36008,
fbtrace_id: 'A-YAgSqKbzPR94XL8QjIyHn'
}
I think the problem lies in my redirect_uri. Apparently, the redirect uri I obtained from the Facebook auth dialog is different from the one that I'm passing to the facebook API in my server side (http://localhost:3000/).
I believe there's something to do with the origin parameter of the redirect_uri. Initial auth dialog request uri indicates that it's origin parameter value is something like "origin=localhost:3000/f370b6cb4b5a9c". I don't know why react-facebook-login add some sort of trailing value at the end of origin param.
https://web.facebook.com/v2.3/dialog/oauth?app_id=249141440286033&auth_type=&cbt=1620173773354&channel_url=https://staticxx.facebook.com/x/connect/xd_arbiter/?version=46#cb=f39300d6265e5c4&domain=localhost&origin=http%3A%2F%2Flocalhost%3A3000%2Ff370b6cb4b5a9c&relation=opener&client_id=249141440286033&display=popup&domain=localhost&e2e={}&fallback_redirect_uri=http://localhost:3000/&locale=en_US&logger_id=f1b3fba38c5e31c&origin=1&redirect_uri=https://staticxx.facebook.com/x/connect/xd_arbiter/?version=46#cb=f17641be4cce4d4&domain=localhost&origin=http%3A%2F%2Flocalhost%3A3000%2Ff370b6cb4b5a9c&relation=opener&frame=f3960892790a6d4&response_type=token,signed_request,graph_domain&return_scopes=false&scope=public_profile,email&sdk=joey&version=v2.3
I tried finding everywhere about this but no luck. Anyone has clue about this, much appreciated.
Are you using middleware to parse the body? if you aren't code could be undefined here.
const facebookOAuth = require('./config/facebookOAuth');
// facebook oauth route
app.post("/api/auth/facebook", async (req, res) => {
try {
const code = req.body.code;
const profile = await facebookOAuth.getProfile(code);
console.log(profile);
res.send({ profile });
} catch (err) {
console.log(err);
res.status(401).send();
}
});

ReactJS and Node.JS [JSON.parse: unexpected character at line 1 column 1 of the JSON data]

I'm getting struggle with this code, so I need a third eye on this to find a solution.
I'm developing a ReactJS app with a REST API with Node.JS (Express), and I'm getting this error:
SyntaxError: "JSON.parse: unexpected character at line 1 column 1 of the JSON data"
I'm using Sequelize ORM to work with Models and Database in Node.JS.
I'm also using CORS module for Node.JS.
This implementation works fine.
// Node.js Route for login
const router = require('express').Router();
const User = require('user');
router.post("/login", async (req, res) => {
try {
await User.findOne({
where: {
email: req.body.email,
password: req.body.password,
}
}).then((user) => {
if (!user) {
return res.send({message: "Login error!"});
} else {
const userData = {id: user.id, email: user.email};
res.send({"user": userData});
}
}).catch((err) => {
return res.send(err);
});
} catch (err) {
return res.send(err);
}
});
// ReactJS for login
loginFunction(e, data) {
e.preventDefault();
fetch('http://localhost:4500/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(json => {
this.setState({'user': json['user']});
})
.catch((err) => {
console.log(err);
this.setState({errors: "Login error"})
});
}
On the other hand, this implementation do not work properly and throws the SyntaxError above:
// Node.JS for Posts
const router = require('express').Router();
const Post = require('post');
router.get("/posts", async (req, res) => {
try {
await Post.findAndCountAll()
.then((posts) => {
res.send({"posts": posts});
}).catch((err) => {
return res.send(err);
});
} catch (err) {
return res.send(err);
}
});
// ReactJS for Posts
postsFunction() {
fetch('http://localhost:4500/posts', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(json => {
this.setState({'posts': json.posts.rows});
})
.catch((err) => {
console.log(err);
this.setState({errors: "Posts error."})
});
}
As you can see both implementation have little differences, What am I missing?
PS: When I test the 2nd implementation on Postman, data is retrieving successfully.
try removing headers when using GET method
headers: {
'Content-Type': 'application/json'
}
Try to use res.json instead of res.send in the node js function that cause the error.
I found the issue!
I follow the (#vengleab so) suggestion:
console log response instead of response => response.json()
I'm realize that response returns an object like this:
Response: {
body: ReadableStream
locked: false
<prototype>: object { … }
bodyUsed: false
headers: Headers { }
ok: true
redirected: false
status: 200
statusText: "OK"
type: "basic"
url: "http://localhost:3000/admin/undefined/posts"
}
The URL attribute contain an undefined value, so when I try to console.log the .env variable API_URL that contains the localhost URL used in this line:
fetch('http://localhost:4500/posts', {
That in real function is:
fetch(process.env.API_URL + '/posts', {
The result of the console.log was undefined.
As it is explained in Create React App docs, the environment variables must start with the prefix REACT_APP_.
Finally the line works as:
fetch(process.env.REACT_APP_API_URL + '/posts', {
I found that it was because my front end react url pointed to the same url as my backend server.js running mongodb. Also clearing the cookies on the browser seems to have helped as well.

Route handler in express is not invoking anything?

I have made a simple textbox which accepts
Youtube Video URL
which slices it's video ID and use fetch to send data to my express server. I am using Youtube Data API v3
//after clicking button sends data
//input fields are defined already.
const sendData = (event) => {
event.preventDefault();
const filterUrl = input2.value.indexOf('&') != -1 ? input2.value.slice(0, input2.value.indexOf('&')) : input2.value;
const url = new URL(filterUrl).searchParams.get("v");
fetch('/', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
urlname: url.toString()
})
})
.then(function(res) {
console.log(res)
})
.catch(function(error) {
console.log(error)
});
}
Here is my Express Handler :
//defined routes and PARAMETER variable is globally defined
app.route('/')
.get((req, res) => {
res.render('container/index', {
title: 'Hello User!',
content: 'Welcome to youtube Comment viewer'
});
})
.post((req, res) => {
console.log("hello")
PARAMETER = req.body.urlname;
console.log(PARAMETER);
res.redirect('/randomCommentView');
});
//get request
app.get('/randomCommentView', (req, res) => {
console.log("inside");
Comments(PARAMETER)
.then((data) => {
res.render('container/comment', {
Comment: 'fgfg'
})
}).catch(err => {
if (err) res.status(404).render('container/index', {
notFound: `Your request couldn't be completed ERR: ${err}`
})
})
console.log(req.body);
});
But when i submit my Youtube video url, The page stays on the same route.
Here's the image of my output:
So it seems like the routes are being called but the page URL is not changing in the web browser .Does anyone know the possible reason for this.
Thanks,
Regards.
Since you're using javascript to make your request, only the javascript will follow your redirection.
What you can do is instead of sending a redirection from the server, send a special code that will trigger a manual redirection (window.location.href = ...) in your client-side javascript code.

Categories