I have built the server and the client and I am having trouble processing a response on the client that the server sends over. I've used res.send(data) and res.json(data), but the response that the client processes doesn't contain any of the information the server has sent back.
Here is my server code. I am deleting an item and just want to send some random data back to see if I can receive it on the client.
app.delete('/deleteReward/:id', (req, res) => {
console.log('\n\n\n\nInside delete\n\n\n\n')
console.log(req.params.id)
var rewardId = req.params.id
const sessionCookie = req.cookies.session || "";
var idToken = ""
var type = ""
if (sessionCookie) {
idToken = sessionCookie['idToken']
type = sessionCookie['type']
}
console.log("Printing session cookie")
console.log(sessionCookie)
admin
.auth()
.verifySessionCookie(idToken, true /** checkRevoked */)
.then((decodedClaims) => {
console.log(decodedClaims.user_id)
deleteReward(decodedClaims.user_id, rewardId)
// res.send("new data being sent")
})
.catch((error) => {
console.log(error)
});
res.json({'key': 'value'})
})
Here is my code on the client-side
for(var i = 0; i < rewardDeleteButtons.length; i++) {
var deleteButton = rewardDeleteButtons[i]
deleteButton.addEventListener('click', function(e) {
console.log(document.cookie)
console.log(this.value)
var response = fetch("/deleteReward/" + this.value, {
method: "DELETE",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"CSRF-Token": Cookies.get("XSRF-TOKEN"),
},
});
response.then((data) => {
console.log(data)
})
})
}
The data I'm getting back looks like this when I console.log it
Response {type: "basic", url: "http://localhost:5000/deleteReward/1", redirected: false, status: 200, ok: true, …}body: (...)bodyUsed: falseheaders: Headers {}ok: trueredirected: falsestatus: 200statusText: "OK"type: "basic"url: "http://localhost:5000/deleteReward/1"[[Prototype]]: Response
I should see something like "{'key': 'value'}" or something like that in the returned JSON but it's not there. Not sure what I'm doing. Couldn't find any examples online of handling a response and extracting data within on the client from Node.
The first then() block of fetch doesn't directly resolve the response body. It resolves the response object. You should return the JSON response from the first resolver and use second then() to use it.
More Info: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
The code should be like
response
.then(res => res.json())
.then(data => console.log(data));
Related
I am writing a simple post request in a Firebase Cloud function, with Axios. This function calls an API endpoint and gets an object of profile details as response. My problem is to correctly return the response to the client.
In the code below, the Cloud Function logs the result correctly. But I can't figure out how to correctly return it to the client from the client-side callGetProfile() function. (Which runs inside a Vue3 method.)
I am probably missing something obvious but am very new to Node.js and HTPP requests.
Thanks for any help!
// MY FUNCTION IN NODE.JS (Firebase Cloud Functions)
exports.getProfile = functions.https.onCall((data, context) => {
var postData = {
profile_id: "xxxxxxxxxxxxxxxxx", //hardcoded here for testing but should be passed in "data" arg.
profile_type: "personal",
};
let axiosConfig = {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'X-API-KEY': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX'
}
};
axios.post('xxxxxxxxxxxxxxxxxxxxxxxxxxxxx', postData, axiosConfig)
.then((res) => {
console.log(res.data) // this works, I get all the data correctly!!
return res // also tried res.data
})
.catch((err) => {
console.log("AXIOS ERROR: ", err);
})
});
// MY FUNCTION CLIENT SIDE (Vue3 method)
const functions = getFunctions();
const callGetProfile() = httpsCallable(functions, "getProfile");
callGetProfile()
.then((result) => {
console.log(result.data) // this doesn't work, data is "null"
})
.catch((e) => console.log(e));
I am using netlify functions to send an email from the frontend and it works fine... as in it does send the email.
However on the clientside (browser) I can't get any response. I need a basic response that would allow me to do a if (status==="success") displayMessage() but I can't seem to get any response on the browser.
I get this message Uncaught (in promise) SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data However on sending the request via POSTMAN I get a response 'Email Sent Succesfully' which is the body part of the callback response.
Here's the function that I am using at .netlify/functions/sendMail
const nodemailer = require("nodemailer");
exports.handler = function (event, context, callback) {
const mailConfig = {
host: "smtp.mailgun.org",
port: 465,
secure: true,
auth: {
user: process.env.MAILGUN_USER,
pass: process.env.MAILGUN_PASSWORD,
},
};
const transporter = nodemailer.createTransport(mailConfig);
transporter.verify((error, success) => {
if (error) {
console.log(error);
} else {
console.log("Ready to send emails");
}
});
const messageData = JSON.parse(event.body);
const { email, name, mobile, message, subject, recipient } = messageData;
console.log(messageData);
const mailOptions = {
from: email,
to: recipient,
subject: subject,
text: message,
};
transporter.sendMail(mailOptions, (error, success) => {
if (error) {
console.log(error);
callback(error);
} else {
console.log("email sent");
callback(null, {
statusCode: 200,
body: "Email sent successfully",
});
}
});
};
and on the client side I have this
const form = document.querySelector("#message");
const submitMessage = (event) => {
event.preventDefault();
const formData = new FormData(form);
formData.append("recipient", "testing#gmail.com");
formData.append("subject", "Submission from website");
const messageData = Object.fromEntries(formData);
console.log(messageData);
const url = ".netlify/functions/sendMail";
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(messageData),
};
fetch(url, options)
.then((response) => response.json())
.then((data) => console.log(data));
};
form.addEventListener("submit", submitMessage);
in the fetch request, I expected data to give me a response so I could trigger some action to display a success message..
Can someone advise me what I am doing wrong here?
I realised what I was doing wrong and here's the solution in case someone else faces the same issues.
In the callback from the netlify function I was sending the body as text
callback(null, {
statusCode: 200,
body: "Email sent successfully",
});
but in the clientside fetch request I was treating it as json
fetch(url, options)
.then((response) => response.json())
.then((data) => console.log(data));
So basically I could either use a response.text() instead of response.json() for the fetch request or use JSON.stringify and return a JSON object from the callback. I preferred the JSON.stringify option as below for the callback
callback(null, {
statusCode: 200,
body: JSON.stringify({
status: "success",
message: "Email sent successfully",
}),
});
I've the below JS code, that is returning status 201,
I'm working it with a local server, that is working correctly once I checked it at thunder client as shown:
My code is:
async function send(params) {
var path = document.querySelector('#path');
var skills = document.querySelector('#skills');
var skillsList = skills.value
skillsList = skillsList.replace(/\n\r?/g, '|');
const dataToSend = JSON.stringify({"path": path.value, "skills": skillsList});
console.log(dataToSend);
let dataReceived = "";
fetch("http://localhost:3000/getSkills", {
credentials: "same-origin",
mode: "cors",
method: "post",
headers: { "Content-Type": "application/json" },
body: dataToSend
}).then(resp => {
if (resp.status === 200) {
return resp.json();
} else {
console.log("Status: " + resp.status)
return Promise.reject("server")
}
}).then(dataJson => {
dataReceived = JSON.parse(dataJson)
console.log(`Received: ${dataReceived}`)
}).catch(err => {
if (err === "server") return
console.log(err)
})
}
Why I'm getting 201, not the returned JSON object as expected, and as shown at thunder client?
Your "thunder client" shows that a 201 response code is a success from your backend (and 2xx codes are Successful Responses according to the HTTP standard)
You explicitly state that if it's not a 200, it's a failure. Change this in your code to accept all 2xx. (window.fetch returns a Response instance, which sets the readonly attribute ok to true if the response code is 2xx MDN)
.then(resp => {
if (resp.ok) {
return resp.json();
} else {
console.log("Status: " + resp.status)
return Promise.reject("server")
}
})
201 means Created,
The request has succeeded and a new resource has been created as a result. This is typically the response sent after POST requests, or some PUT requests. MDN
I am trying to load a data from my firebase backend but getting this error
Uncaught (in promise) TypeError: response.json is not a function
my code is as below :
import axios from 'axios';
export const loadData = ({ commit }) => {
console.log('getting data from server...');
axios
.get('data.json')
.then(response => response.json())
.then(data => {
if (data) {
const stocks = data.stocks;
const stockPortfolio = data.stockPortfolio;
const funds = data.funds;
const portfolio = {
stockPortfolio,
funds
};
commit('SET_STOCKS', stocks);
commit('SET_PORTFOLIO', portfolio);
console.log('Commit done ');
}
});
};
however, if I try response.data instead of response.json it works and successfully loads the data, so I am curious what the difference is and why the first one doesn't work.
Because of the axios package, it has a specific response schema https://github.com/axios/axios#response-schema
The response for a request contains the following information.
{
// `data` is the response that was provided by the server
data: {},
// `status` is the HTTP status code from the server response
status: 200,
// `statusText` is the HTTP status message from the server response
statusText: 'OK',
// `headers` the headers that the server responded with
// All header names are lower cased
headers: {},
// `config` is the config that was provided to `axios` for the request
config: {},
// `request` is the request that generated this response
// It is the last ClientRequest instance in node.js (in redirects)
// and an XMLHttpRequest instance in the browser
request: {}
}
With axios you don't need an extra .json() .Responses are already served as javascript object, no need to parse, simply get response and access data. You could use directly something like
axios.get('/user/12345')
.then(function (response) {
console.log(response.data);
console.log(response.status);
console.log(response.statusText);
console.log(response.headers);
console.log(response.config);
});
You only need to use the Body.json() method if you are trying to resolve the promise from a Response stream. You may read more about it on the documentation. One use case of doing so would be when you are making a HTTP request using the fetch API, whereby you will have to call Body.json() to return the response body.
let response = await fetch(url);
if (response.ok) { // if HTTP-status is 200-299
// get the response body (the method explained below)
let json = await response.json();
} else {
alert("HTTP-Error: " + response.status);
}
For axios, you only need to resolve the promose after making a GET request
axios.get(url[, config])
and thus, the following code below works, as the returned response body is handled within the .then() block when you resolve the promise.
axios
.get('data.json')
.then(response => console.log(response.data))
const CollectData = async () => {
let result = await fetch('http://localhost:5400/Enquiry', {
method: "post",
body: JSON.stringify({ name, email, contact, message }),
headers: {
"Content-Type": "application/json",
}
});
result = await result.json();
console.log(result);
if (result) {
navigate("/");
}
I am building my web app on NextJS NodeJS and Express, I am running two servers on localhost 3000 for next and 9000 for express.
I have a form with two input fields and I am sending the state with axios post to the url with data, on the server-side I am receiving that request and sending back the same received data as a response.
I get the response from server with data: success and my data in config.data
Why is my data in config data and how can I get it out from this JSON so I can pass it to a variable.
As for grabbing the data from the config.data, I have tried for loops but they either push 56 elements of 56 numbers to the empty array or don't do nothing.
Client side:
state = {
bank_name: '',
account_number: ''
}
...
onSubmit = (e) => {
e.preventDefault()
axios.post('http://localhost:9000/api/bank', {
bankName: this.state.bank_name,
accNumber: this.state.account_number
})
.then(res => {
console.log(res)
}).catch(err => console.log(err))
}
Server side:
router.post('/', (req, res) => {
const {reqData} = req;
res.send(reqData);
})
Console log from client side ( console.log(res) ):
{
config: {
url: "http://localhost:9000/api/bank",
method: "post",
data: '{"bankName":"some new bank","accNumber":"39276542934235"}'
},
data: "success",
headers: "...",
request: "...",
status: 200,
statusText: "OK",
__proto__: Object
}
...
When I target res.config.data.bankName I get undefined.
I believe this has to do with the server response being as it is, or not parsing the data server receives in the first place, or it is due to promises.
Any input would be helpful, thanks
That res.config.data is string so parse it first JSON.parse(res.config.data) and then access the bankName.
Also you must be using body-parser at the express end. And so post data resides in req.body you should send that back not the whole req IMO.
Express:
router.post('/', (req, res) => {
const reqData = req.body;
return res.send(reqData);
});
Axios: (returned data should be in res.data)
axios.post('http://localhost:9000/api/bank', {
bankName: this.state.bank_name,
accNumber: this.state.account_number
})
.then(res => {
console.log(res.data);
}).catch(err => console.log(err))
}