Circular JSON, when trying to stringify a JS object - javascript

we have this object, we need to get it as JSON instead of JS object, so we do it with JSON.stringify()
and we receive this error:
Converting circular structure to JSON
> --> starting at object with constructor 'ClientRequest'
> | property 'socket' -> object with constructor 'TLSSocket'
> --- property '_httpMessage' closes the circle
and here is my whole end-point, I think it might have something to do with Axios, please note we uses TypeScript so actually this file is not .js file but .ts:
app.post('/payment-key-request', async (req: any, res: any) => {
const {auth_token, order_id} = req.body;
const payload1 = {
auth_token,
amount_cents: 100,
expiration: 3600,
order_id,
billing_data: {
apartment: 803,
email: "claudette09#exa.com",
floor: 42,
first_name: "Clifford",
street: "Ethan Land",
building: 8028,
phone_number: 9135210487,
shipping_method: "PKG",
postal_code: 41523,
city: "Jaskolskiburgh",
country: "CR",
last_name: "Nicolas",
state: "Utah"
},
currency: "EGP",
integration_id: 1 // something goes off here
};
let cache: any = [];
await Axios.post(
"https://accept.paymobsolutions.com/api/acceptance/payment_keys",
JSON.stringify(payload1),
{
headers: { "Content-Type": "application/json" }
}
)
.then((resp: any) => {
res.status(200).json({ ...resp });
})
.catch((error: any) => {
if (error.response) {
console.log("// Request made and server responded");
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log("// The request was made but no response was received");
console.log(error.request);
} else {
console.log(
"// Something happened in setting up the request that triggered an Error"
);
console.log(error.message);
}
res.status(400).json({ ...error });
});
cache = null;
})

Instead of trying to respond with the entire response object, you should send just the parsed body:
res.status(200).json(resp.data);
Same with the error case:
res.status(400).json(error.response.data);

Related

Sending POST request to a Next.js API route sending a 500 Internal Server Error

Here is the code for createComment.ts file which is a Next.js api route
import type { NextApiRequest, NextApiResponse } from 'next'
import sanityClient from "#sanity/client"
const config = {
dataset: process.env.NEXT_PUBLIC_SANITY_DATSET,
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
useCdn: process.env.NODE_ENV === "production",
token: process.env.SANITY_API_TOKEN
}
const client = sanityClient(config);
export default async function createComment(
req: NextApiRequest,
res: NextApiResponse
) {
const {_id, name, email, comment} = req.body
try {
await client.create({
_type: 'comment',
post: {
_type: "reference",
_ref: _id
},
name,
email,
comment
})
} catch (error) {
return res.status(500).json({message: "Couldn't submit comment", error})
}
console.log("Comment submitted")
res.status(200).json({ message: 'Comment Submitted Successfully' })
}
And here is my frontend code which is being used to send a POST request to the api route via Fetch API
const onSubmit: SubmitHandler<IFormInput> = (data) => {
fetch("/api/createComment", {
method: "POST",
body: JSON.stringify(data),
})
.then(() => {
console.log(data);
})
.catch((error) => {
console.log(error);
});
};
I am getting this error even after clearing my cache and restarting the server several times, but no luck.
Most probably the error comes from sanityClient. Try to make some checks for the .env variables or the token itself that comes from sanity are not valid ... who knows?

VUE application Response data useing Axios

I'm developing a VUE application, and I am trying to figure out how to handle post responses in Axios. I wrote it and used vue-router to make the fetch but decided to try out Axios.
Axious code:
methods: {
sendForm () {
console.log("submitHandler called - success!");
const payload = {
first_name: this.event.firstName,
last_name: this.event.lastName,
email: this.event.email,
password: this.event.password,
name: this.event.agencyName,
abbreviation: this.event.abbreviation,
type: this.event.agencyType,
address: this.event.agencyAddress,
city: this.event.agencyCity,
state: this.event.state,
zipcode: this.event.zipcode,
phone: this.event.phone,
}
axios.post(process.env.VUE_APP_API_URL+"/agency/add",payload)
.then(function (response) {
console.log('Response', response)
//reformat returned expiration date for displaying on webpage
console.log("Expiry date:", response.data.data.agency.expiry);
let expd = dayjs(response.data.data.agency.expiry).format("dddd, MMMM D YYYY");
//Write retunred values to storeage
store.user = {
id: response.data.data.user.id,
first_name: response.data.data.user.first_name,
last_name: response.data.data.user.last_name,
email: response.data.data.user.email,
agency_name: response.data.data.agency.name,
expiry_date: expd,
}
router.push("/SignUpConfirm");
})
.catch(function (error) {
console.log('Error', error.message);
Swal.fire({
icon: 'error',
title: 'Oops...',
text: error.message,
})
})
}
}
My issue/question is, for some reason, I have to use "response.data.data.foo" to drill to the response I want.
When I used the built-in view router, I just used "data.foo"
Vue-router option:
methods: {
submitHandler() {
console.log("submitHandler called - success!");
const payload = {
first_name: this.firstName,
last_name: this.lastName,
email: this.email,
password: this.password,
agency_name: this.agencyName,
abbreviation: this.abbreviation,
agency_type: this.agencyType,
agency_address: this.agencyAddress,
agency_city: this.agencyCity,
state: this.state,
zipcode: this.zipcode,
phone: this.phone,
}
const requestOptions = {
method: "POST",
body: JSON.stringify(payload),
}
fetch(process.env.VUE_APP_API_URL+"/agency/add", requestOptions)
.then((response) => response.json())
.then((response) => {
if (response.error) {
console.log("Error:", response.message);
Swal.fire({
icon: 'error',
title: 'Oops...',
text: response.message,
})
} else {
//reformat returned expiration date for displaying on webpage
console.log("Expiry date:", response.data.agency.expiry);
let expd = dayjs(response.data.agency.expiry).format("dddd, MMMM D YYYY");
//Write retunred values to storeage
store.user = {
id: response.data.user.id,
first_name: response.data.user.first_name,
last_name: response.data.user.last_name,
email: response.data.user.email,
agency_name: response.data.agency.name,
expiry_date: expd,
}
router.push("/SignUpConfirm");
}
})
}
}
Your API response is probably something like this (after parsing JSON of course)
{
data: {
user: {
......
}
}
}
For clarity, lets say it is instead returning
{
topLevel: {
nextLevel: {
......
}
}
}
so, below, toplevel would actually be data, and nextLevel would actually be user ... but, using these abstract names of toplevel and nextLevel should help illustrate why you end up with data.data in axios
axios response schema is as follows
{
data: {}, // server response
status: 200, // response status
statusText: 'OK', // response status text
headers: {}, // response headers
// etc - there's more but not relevant
}
So in
axios.post(....)
.then(function (response) {
})
then nextLevel is clearly response.data.topLevel.nextlevel
Note that the response from the server here is a property of the data property of the response variable - i.e. two "levels" inside the response variable
When using fetch
fetch(....)
.then(response => response.json())
.then(response => .....)
(it doesn't help clarity that you use response in both .then by the way, I'd use result in the second .then)
in the above, the FIRST response is
{
status: 200, // response status
statusText: 'OK', // response status text
headers: {}, // response headers
body: // a readableStream of the response body
json() {}, // method to parse the body as json
// .... etc
}
and the second response is the parsed JSON response from your server,
so in this case nextLevel is response.topLevel.nextLevel
And the response from the server here is a property of (the second) response variable

CastError: Cast to string failed for value (Mongoose, React js)

I am getting an email from lstate which is a state of useReducer. I am getting lstate value by using Context api and useContext. But my problem is that i transfered the lstate using fetch api to my backend auth.js to get the document of the required email from the MongoDB. But i am not getting email from lstate at backend i am getting objects.
Account.jsx
const Account = () => {
const { lstate } = useContext(LoginContext);
const LoginData = async () => {
console.log(`my lstate in login function ${lstate}`);
await fetch('/account', {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
lstate
})
}).then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
})
}
useEffect(() => {
LoginData();
}, []);
auth.js
router.post('/account', async (req, res) => {
try {
const email = req.body;
console.log(`data from account ${email}`);
const data = await CustomerModel.findOne({ email: email });
if (data) {
return res.json(data);
}
} catch (error) {
console.log(error);
}
})
Console Error
data from account [object Object]
CastError: Cast to string failed for value "{ lstate: 'usman4276#gmail.com' }" at path "email" for model "Customer_reg"
at model.Query.exec (C:\MERN stack\online-cattle-shop\backend\node_modules\mongoose\lib\query.js:4408:21)
at model.Query.Query.then (C:\MERN stack\online-cattle-shop\backend\node_modules\mongoose\lib\query.jsbackend\node_modules\mongoose\lib\query.js:4502:15)
at processTicksAndRejections (internal/process/task_queues.js:93:5) {
messageFormat: undefined,
stringValue: `"{ lstate: 'usman4276#gmail.com' }"`, kind: 'string',
value: { lstate: 'usman4276#gmail.com' },
path: 'email',
reason: null
}
should be
const { email } = req.body;
OR
const email = req.body.email;
You should also add conditional checks.
E.g.
if (!email) throw new Error ('Email Required')
The code in the client is sending a JSON and the key lstate contains the actual mail.
you need to do
const email = req.body.email.lstate;
const data = await CustomerModel.findOne({ email });

How to extract data from an array of objects to render a list in an html email template? Using React/Formik/Sendgrid

So, basically I have a form data that I am having trouble parsing correctly. I keep getting [object Object]'s in the response for the listPets variable. Every other variable is mapping correctly. Anyone have any ideas on how I could go about this? :)
<Formik
initialValues={{
email: '',
password: '',
jobType: '',
comments: '',
cookies: [],
terms: '',
newsletter: '',
firstName: '',
pets: [{ type: '', name: '', id: '1' }]
}}
validationSchema={ LoginSchema }
onSubmit={
async data => {
await sleep(1000);
setStatus(prevStatus => ({ ...prevStatus }));
const res = await fetch('/api/send', { method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const text = await res.text();
handleResponse(res.status, text);
}
}
>
const sgMail = require('#sendgrid/mail');
export default async function(req, res){
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const { email, comments, firstName, cookies, jobType, pets } = req.body;
const content = {
to: '',
from: email,
subject: `New Message From - ${email}`,
text: comments,
html: `
<p>Hi, ${firstName}.</p>
<p>${comments}</p>
<p>${cookies}</p>
<p>${jobType}</p>
<p>${listPets}</p>
`
};
try {
console.log('Content', content);
res.status(200).send('Message sent successfully.');
} catch (error) {
console.log('ERROR', error);
res.status(400).send('Message not sent.');
}
}
Why not use JSON.stringify(pets) to debug whats happening? I would have commented but i dont have enough reputation.

passing parameters in post request axios

i have an object that i will use in post request using axios
employee:{
name: 'test',
email: 'test#gmail.com',
password: '123456',
role: {
created_at:"2018-08-03 07:34:30"
deleted_at:null
id:2
role_name:"employee"
updated_at:"2018-08-03 07:34:30"
}
},
this is my post request
axios.post('api/employees', vm.employee)
.then( response => {
alert("Employee Inserted");
vm.errors.clear();
vm.setFalse();
vm.fetchEmployees();
})
.catch( error => {
vm.errors.record(error.response.data);
});
how can I pass in post request only the role_name in role object together with name, email and password
If you mean headers by parameters then you can try:
var options = {
headers: {'X-My-Custom-Header': 'Header-Value'}
};
axios.post('api/employees', vm.employee, options);
Other wise just create a a body like this:
var options = {
headers: {'X-My-Custom-Header': 'Header-Value'}
};
axios.post('api/employees', {
name: vm.employee.name,
role: {
role_name: vm.employee.role.role_name
}
}, options);
I think this work for you.
axios.post('api/employees', {name: employee.name, email: employee.email, role_name: employee.role.role_name})
.then( response => {
alert("Employee Inserted");
vm.errors.clear();
vm.setFalse();
vm.fetchEmployees();
})
.catch( error => {
vm.errors.record(error.response.data);
});
If ES2015 is ok then this would be a shorter way to pass the data:
axios.post('api/employees', {
...employee,
role: { role_name: employee.role.role_name }
}) ...

Categories

Resources