Can't send payload to back-end from front-end - javascript

I'm making a chat bot where people get coins each 30 minutes, they can then spend those coins. When they spend those coins they need to be deducted, so I need to catch their command in my front-end and deduct the coins from their profile in my back-end.
This is a case of my switch case in which I catch the command that's being utilised
case `!gayOverlay`:
const requiredKluiten = 50;
fetch(`/api/users/${userstate.username}`) // fetch from Express.js server
.then(response => response.json())
.then(result => {
if (result.instakluiten >= requiredKluiten) {
client.action(channel, `${userstate[`display-name`]}, you've got enough instakluiten for this.`);
const method = `PATCH`;
const payload = {requiredKluiten};
const body = JSON.stringify(payload);
const headers = `Content-Type: application/json`;
return fetch(`/api/users/${userstate.username}`, {method, body, headers})
.then(r => console.log(`Result is `, d));
}else{
client.action(channel, `${userstate[`display-name`]}, you don't have enough instakluiten for this, you need ${requiredKluiten - result.instakluiten} more.`);
}
});
break;
I'm using PATCH to update my viewers' coins (I read Please do not patch like an idiot, but people in the comments were also against the method, so I'm not sure what the correct way is anymore now...), when I send data with postman my req.body in my back-end is filled with the data I added. However, when I execute my function (which also should have data because of my payload), my req.body is an empty object. What am I doing wrong here?
This is what's happening on the server side
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/api/users/:username', (req, res) => {
let username = req.params.username;
findUserInApi(username)
.then(foundUser => {
console.log(`foundUser is ${foundUser}`);
if (!foundUser) {
res.status(403).send('User not found in api yet');
}else{
res.json(foundUser);
}
});
});
Update
This is what's being returned in the then after my patch (changed it to PUT after the comment of Alex) https://puu.sh/shO57/362b639545.png
Update
Even when trying it like this (because of this post) it makes no difference
const data = JSON.stringify(payload);
const body = new FormData();
body.append(`json`, data);
Update
When using postman my body is always: {'requiredKluiten': 50}.
When I remove the headers (that were automatically set to application/x-www-form-urlencoded when choosing x-www-form-urlencoded to send my data) I get an empty object with Postman. When the headers are added again with x-www-form-urlencoded it works. When I select form-data however I get as req.body:
{ '------WebKitFormBoundarySAXAR2jfhUJt39US\r\nContent-Disposition: form-data; name': '"requiredKluiten"\r\n\r\n50\r\n------WebKitFormBoundarySAXAR2jfhUJt39US--\r\n' }
However, when adding the headers to my code, it still doesn't work when executing my fetch... I must still be doing something wrong :/...
This is what's being executed right now, any flaws to be spotted?
case `!gayOverlay`:
const requiredKluiten = 50;
fetch(`/api/users/${userstate.username}`) // fetch from Express.js server
.then(response => response.json())
.then(result => {
if (result.instakluiten >= requiredKluiten) {
client.action(channel, `${userstate[`display-name`]}, you've got enough instakluiten for this.`);
const method = `PUT`;
const payload = {requiredKluiten};
const body = JSON.stringify(payload);
const headers = `Content-Type: application/x-www-form-urlencoded`;
return fetch(`/api/users/${userstate.username}`, {method, body, headers})
.then(d => console.log(`Result is `, d));
}else{
client.action(channel, `${userstate[`display-name`]}, you don't have enough instakluiten for this, you need ${requiredKluiten - result.instakluiten} more.`);
}
});

Related

Nested promises receiving 301 error code and cors for second fetch

I am attempting to create an API where you type in a player's name and you get the player position, team and then stats. The only thing is that while it uses the same public API, Ball Don't Lie, it requires two different fetches. So I am attempting to get the player id from the first promise and then feed it into the second. I get the first info and the id but when I attempt the second fetch I get this: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://balldontlie.io/api/v1/stats?season[]=2020&player_ids[]=237. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
Status code: 301.
Here is my code:
//The user will enter a NBA player, click on the type of stat, team, and receive their stats. Default will be all stats?
document.querySelector('button').addEventListener('click', apiRequest)
function apiRequest() {
var player = document.querySelector('input').value;
var season = document.querySelector('input[type="number"]').value;
var id;
fetch(`https://www.balldontlie.io/api/v1/players/?search=${player}`)
.then(res => res.json()) //parse response as JSON
.then(data => {
object = data;
id = object.data[0].id;
document.querySelector('h2').innerText = `${data.data[0].first_name} ${data.data[0].last_name}`
document.querySelector('.team').innerText = data.data[0].team['full_name']
document.querySelector('.position').innerText = data.data[0].position
//nested fetches to send player id from one promise to another promise to get player stats
})
.then (async data => {
await new Promise(data => {
return fetch (`https://balldontlie.io/api/v1/stats?season[]=${season}&player_ids[]=${id}`)
.then(response => response.json())
.then(data => {
array[index] = {...e, ...data};
console.log(data)
})
})
})
.catch(err => {
console.log(`error ${err}`)
})
}
I am using Node.js and Express so I am using CORS package. Below is my server.js.
const express = require('express');
const app = express();
const PORT = 8000;
const cors = require('cors');
app.use(cors());
//Body Parsing
app.use( express.json() );
app.use(express.urlencoded({
extended: true}));
app.use(express.static("public"));
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
})
app.listen(PORT, () => {
console.log(`The server is running on ${PORT}`);
})
First off, your code is a bit confused for the second fetch() operation and in fact the promise created here in await new Promise(data => {...}). never resolves because you never call the first argument to the executor function (which you have inappropriately named data when it should be resolve).
Second, you don't have proper error handling on some of your promises so you may not be clearly seeing what errors are happening here.
So, first I'd suggest cleaning up the code and error handling and then rerun it to report exactly what you get:
//The user will enter a NBA player, click on the type of stat, team, and receive their stats. Default will be all stats?
document.querySelector('button').addEventListener('click', apiRequest)
function apiRequest() {
const player = document.querySelector('input').value;
const season = document.querySelector('input[type="number"]').value;
console.log("about to run first fetch()");
fetch(`https://www.balldontlie.io/api/v1/players/?search=${player}`)
.then(res => res.json()) //parse response as JSON
.then(data => {
console.log("got first fetch() result");
const object = data;
const id = object.data[0].id;
document.querySelector('h2').innerText = `${data.data[0].first_name} ${data.data[0].last_name}`;
document.querySelector('.team').innerText = data.data[0].team['full_name'];
document.querySelector('.position').innerText = data.data[0].position;
//nested fetches to send player id from one promise to another promise to get player stats
console.log("about to run second fetch()");
return fetch(`https://balldontlie.io/api/v1/stats?season[]=${season}&player_ids[]=${id}`)
.then(response => response.json())
.then(data => {
console.log("got second fetch() result");
// not sure what array is here?
// It isn't declared anywhere - shouldn't be doing this
array[index] = { ...e, ...data };
console.log(data)
});
}).catch(err => {
console.log(`error ${err}`)
});
}
And, I've added a little more logging about which fetch() operation is running so if you see an error displayed, you can see which fetch() operation caused it.

400 bad request with ReactJs

I'm trying to make a post request to the server,but it returns 400 error.
:
this is react function
const handleSubmit = () => {
const bookInstanceObject = {
imprint: imprint,
};
axios
.post('http://localhost:3001/catalog/bookinstance/create', bookInstanceObject)
.then(res => {
console.log(res.data);
})
.catch(error => {
console.log(error);
});
};
and this is the server side:
router.post('/bookinstance/create', (request, response, next) => {
const body = request.body;
const bookInstance = new BookInstance({
imprint: body.title,
});
bookInstance
.save()
.then(savedBook => {
response.json(savedBook.toJSON());
})
.catch(error => next(error));
});
any idea ?
What I think is happening
The front end's handleSubmit function is POSTing to /catalog/bookinstance/create, while the server is expecting it to come to /bookinstance/create.
Simple typo, easy to miss when your stressing over it not working.
How to fix?
Change the URLs to match.
Either:
change the front-end's POST url to /bookinstance/create,
or:
change the server's expected route to router.post('/catalog/bookinstance/create',
Why is it a GET in the error log?
I don't know but I suspect that this error is about a GET request somewhere else in your code.
Please let us know in the comments if the error goes away with this fix. (Assuming my fix works)

Code is not working as i want to fetch data based on filter

i sent a request to the mongodb to get some data according to email.my client side code is working
properly .
code is here:
useEffect(()=>{
const email = user?.email;
// console.log(email)
const url = `http://localhost:5000/services?email=${email}`;
console.log(url)
fetch(url)
.then(res => res.json())
.then(data => setItems(data))
},[user])
console.log showing the data as i expected
but the problem start with the backend. i tried console.log to get the email and other thing but the code is not showing nothing even not a single error.
here is the code i wrote for api with express:
app.get('/services',async(req,res)=>{
const email = req.query.email;
console.log(email)
const query = {email:email};
const cursor = serviceCollection.find(query);
const item = await cursor.toArray();
res.send(item);
});
So far I didn't see any issue with your code.
Have you tried to call your GET request from the browser directly?
You might check on req and res to see the incoming data to that endpoint (/services)
You also can try to add the request options in your fetch method
var requestOptions = {
method: 'GET',
redirect: 'follow'
};
const email = user?.email;
const url = `http://localhost:5000/services?email=${email}`;
fetch(url , requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
And I suggest you to using Postman, to call that endpoint. It will easier to debug the API using 3rd party app like Postman.

How to access DB from a function and only then send a post request?

I need help to integrate a few actions inside a function.
I get a call from PayPal, then i need to :
Access my DB to compare.
If ok send 200 OK
Send the request body back.
Currently - I do (3) only, and it somehow works without (2).
exports.contentServer = functions.https.onRequest((request, response) => {
....
....
if(request.path === paid)
{
if (request.method !== "POST")
response.status(405).send("Method Not Allowed");
else {
let ipnTransactionMessage = request.body;
let formUrlEncodedBody = querystring.stringify(ipnTransactionMessage);
let verificationBody = `cmd=_notify-validate&${formUrlEncodedBody}`;
//______________
//** at this point i need to read a firebase collection and return 200OK , ONLY THEN DO THE POST BELOW
var docRef = admin.firestore().collection('All').doc(ipnTransactionMessage.custom);
docRef.once('value').then(function(snapshot) {
console("our data to compare",snapshot);
res.status(200); // ?
});
//**** how do i do the next only after the previous ?
let options = {
method: 'POST',
uri: "https://ipnpb.sandbox.paypal.com/cgi-bin/webscr",
body: verificationBody
};
return rp(options)
.then(body => {
if (body === "VERIFIED") {
//** we are done here - and this actually works already
})
.then(docReference => {
console.log("Request completed");
return response.send({ result: 'ok' });
})
.catch(error => {
console.log(error);
return response.status(500).send(error);
});
See the comment in the code. After reading my DB and respond with 200 OK , only then i would like to send back the body as I do.
As Doug mentioned the code needs to go in the then clause:
I took a part of your code to shaow where the code to get executed only when firestore answers can go.
//** at this point i need to read a firebase collection and return 200OK , ONLY THEN DO THE POST BELOW
var docRef = admin.firestore().collection('All').doc(ipnTransactionMessage.custom);
docRef.once('value').then(function(snapshot) {
console("our data to compare",snapshot);
res.status(200); //
if(snapshot.exists){
// ---------------------------------
// The code that you want to get executed only
// firestore answers Goes Here
// ---------------------------------
}
});

Website does not allow about half our users to login. Cookies issue. Ubuntu

So to be honest I am not sure how much I can share here. I saw a similar post that was solved on the users end and did not actually lead to a solution on mine. If someone wants the website for testing please let me know or if I can post it here to be simple, I will as well.
So here it goes. I cannot personally replicate the issue, which is making it hard to test and I am out of my depth as is. I have watched others with the issue and this is how we have got this far.
We run a discord community and use Auth from Discord to pull in data from our members and use that for features on the site.
That being said - No roles are the issue here. We have whittled the problem down to a cookie. The website creates a cookie, which goes away during the Auth redirect, then comes back and prevents people from loading the site. Gives a 504 Gateway error. Once I get the users to delete the cookie, they can then load the website again - however they are not logged in.
Have been beating our heads against multiple walls for the past week and we cannot get it down.
I will provide some code here - Hoping this will show some issue, but I imagine it will not. Please let me know if I can provide any more clarity.
const r = require('express').Router();
const fetch = require('node-fetch');
const btoa = require('btoa');
const FormData = require("form-data");
const { catchAsync } = require('./utils/utils.js');
const session = require('express-session');
const redir = encodeURIComponent(process.env.DISCORDCALLBACK)
r.get("/login", (req, res) => {
res.redirect(`https://discord.com/api/v6/oauth2/authorize?client_id=${process.env.CID}&response_type=code&scope=identify%20email`);
});
r.get("/logout", (req, res) => {
if(req.session.accessToken.length > 1) {
req.session.accessToken = "";
res.redirect("/");
} else {
res.redirect("/");
}
})
r.get("/callback", catchAsync(async (req, res) => {
if (!req.query.code) throw new Error("NoCodeProvided");
const code = req.query.code;
//const creds = btoa(`${process.env.CID}:${process.env.SECRET}`);
const data = new FormData()
data.append("client_id", process.env.CID);
data.append("client_secret", process.env.SECRET);
data.append("grant_type", "authorization_code");
data.append("code", code);
fetch(`https://discord.com/api/v6/oauth2/token`, {
method: "POST",
//headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: data
})
.then(res => res.json())
.then(json => {
fetch("http://discord.com/api/v6/users/#me", {
method: "POST",
headers: { "Authorization": `${json.token_type} ${json.access_token}` }
})
.then(res => res.json())
.then(user => {
req.session.accessToken = `${json.access_token}`
req.session.cookie.maxAge = 86400000;
req.session.save(err => {
if(err) return console.log(err)
res.redirect("/");
})
})
.catch(err => {
console.log(err)
})
})
.catch(err => {
console.log(err)
})
}));
//export route(s)
module.exports = r;
Okay guys - so I just wanted to update you on what happened. I am thankful for the help and sorry for the waste of time.
One of our programmers said it best: "Lesson learned. Never hardcode values."
For one of Discord's call back for member roles. We had hard coded in a Discord Member ID. This lead to an error and for some reason we still do not understand, half of us being able to get in and half out...
We changed that ID to .env file that we can handle on the Pipeline and boom. People are in.
Thanks for the help!

Categories

Resources