How can I resolve the error of 'serializing' from getServerSideProps in Next.js - javascript

I just changed the server from const server = "https://backend.yourguide.pk" to const server = "https://stage.yourguide.pk", and now this error is shown. How to resolve it?
getServerSideProps's code:
export async function getServerSideProps(context) {
let experience = [];
const server = 'stage.yourguide.pk';
try {
const data = await fetch(
`${server}/api/user/getallexperience?title=${context.params.experiencesTitle}`,
{
method: 'GET',
headers: { 'Content-Type': 'application/json' },
}
);
experience = await data.json();
} catch (error) {
console.log('error is ', error);
}
return {
props: {
title: context.params.experiencesTitle,
experience: experience.results,
},
};
}
error - SerializableError: Error serializing .experiences returned from getServerSideProps in "/".
Reason: undefined cannot be serialized as JSON. Please use null or omit this value.

For some reason, experience is being set to undefined, and undefined is not a valid JSON value. This can be addressed with the help of a check, like so:
export async function getServerSideProps(context) {
let experience;
const server = "stage.yourguide.pk";
try {
const data = await fetch(
`${server}/api/user/getallexperience?title=${context.params?.experiencesTitle}`,
{
method: "GET",
headers: { "Content-Type": "application/json" },
}
);
experience = await data.json();
} catch (error) {
console.log("error is ", error);
}
return {
props: {
title: context.params?.experiencesTitle || null,
experience: experience?.results || null,
},
};
}
Now, why you are getting undefined? Well, this can be because you are not using the correct endpoint, or path, or not giving the correct params, etc. Also, your error is saying .experiences while you have .experience.
Make sure you are not making any typos.

Related

Getting undefined in API call via Fetch - Express Nuxt

I am extremely stuck on a task using Express, API, Fetch.
I am using Nuxt + Shopify API endpoints to grab data such as orders like below
This is my express API Endpoint.
The results should return an array of objects ( orders )
const bodyParser = require('body-parser')
const app = require('express')()
const axios = require('axios')
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.post('/getJSON', async (req, res) => {
const { customerID } = req.body
const id = Buffer.from(customerID, 'base64')
.toString('binary')
.split('gid://shopify/Customer/')
.pop()
console.log('id is', id)
const endpoint = `https://test.myshopify.com/admin/api/2020-07/customers/${id}/orders.json`
try {
const response = await axios.get(endpoint, {
headers: {
'Content-Type': 'application/json',
'X-Shopify-Access-Token': '*****************'
}
})
res.status(200).json(response.data.orders)
} catch (error) {
res.status(500).send(error)
}
})
module.exports = app
Now, in my Nuxt store.js, I am using fetch to make a post requests to that endpoint above.
async function apiPost(endpoint, { data }) {
await fetch(`/api${endpoint}/getJSON`, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
}).then(async (res) => {
const contentType = res.headers.get('content-type')
if (contentType.startsWith('text/html')) {
return res.text()
}
if (contentType.startsWith('application/json')) {
await res.json()
}
})
}
When I console.log res.json(), it is a promise
Since it is a promise, I wanted to see what the results were anyways.
res.json().then((resp) => {
console.log('resp is', resp)
})
Turns out the rest is an array of objects.
However, I do not know how to return this object correctly, as the "ordersResponse" below is always undefined !
Below is a function calling the apiPost passing in the 'endpoint'. However, the orderResponse is undefined. I have tried solutions, but all of them end up as orderResponse being undefined.
async fetchOrders({ state, dispatch, commit }, payload) {
try {
const ordersResponse = await apiPost('/customer-orders', {
data: { customerID: state.customer.id }
})
console.log('ordersResponse', ordersResponse) // **undefined**
} catch (error) {
console.error(error)
throw error
}
},
Any help is appreciated
It looks like the apiPost function needs to make a return from within the 'application/json' if block.
if (contentType.startsWith('application/json')) {
return res.json()
}
You should then receive data back when calling it for the ordersResponse variable.

How can I RETURN Axios error to client? (not only logging)

I know this has been asked many times but what I am facing is a really annoying problem.
I have my server which returns error string with status code 500. When i use axios and catch the error, i can log it easily, but when i return it, i can try everything but its gives me undefined, or it doesn't append anything.
export const submitCheckout = async (betImport, ticket_id, token) => {
const res = await axios({
method: "post",
url: rootUrl + "bets/checkout/" + ticket_id,
headers: {
"x-auth-token": token,
},
data: {
betImport,
},
}).catch(({ response }) => {
console.log(response.status) //this works
return response;
});
return res.data;
};
//HERE I CALL THE FUNCTION
const res = await submitCheckout(sum, ticket_id, token);
//here i can access only the body of the error, even if i try to append something to it.
if (res.ticket_id) {
emptyTicket();
setmodal({
show: true,
title: "SUCCESS",
subtitle: "BET PLACED",
maxwin: `${res.maxWin}`,
ticketId: `${res.ticket_id}`,
account_sum: `${res.account_sum}`,
});
ModifyAccountUser(user, res.account_sum);
} else {
setmodal({
title: "ERROR",
show: true,
status: `${res.status}`,
error: `${res}`,
});
if (res.toString().includes("Token")) history.push("/login");
}
//WHAT I WANT TO DO
export const submitCheckout = async (betImport, ticket_id, token) => {
const res = await axios({
method: "post",
url: rootUrl + "bets/checkout/" + ticket_id,
headers: {
"x-auth-token": token,
},
data: {
betImport,
},
}).catch(({ response }) => {
return {...response, response.status}; //this returns the body only,
return {res: response, status: response.status}; //this crashes,
return response + "-"+ response.status}; //this was my desperation attack and failed as well
});
return res.data;
};
Throw an error and put your response inside it as a string. Then access it in your promise with error.message:
async function foo(){
try{
const res = await ax.post("url", {params})
return res
}
catch(err){
throw new Error("my error message")
}
}
//then
foo()
.then(res=> do stuff)
.catch(err=> err.message)
You can try this.
try {
let res = await Axios({
method: {method},
URL: {url},
data: {body}
});
let data = res.data;
return data;
} catch (error) {
console.log(error.response); // this is the main part. Use the response property from the error object
return error.response;
}

componentwillmount() Uncaught Error: Actions must be plain objects. Use custom middleware for async actions

I'm implementing get all image by type with redux-saga. I have 2 types, let's say, type kristik and type motif.
When I'm implementing type kristik, it got successful response, but when it comes to type motif, the response is error.
here my code that has the error in console
componentWillMount() => {
const { dispatch } = this.props;
dispatch(getAllMotif());
}
I got error in dispatch(getAllMotif()); in commponentWillMount()
Here my getAllMotif() code
getAllMotif(token) {
const path = `motif`;
const method = 'get';
return request.process(method, path, null, token);
},
Here my sagas getAllMotif code
export function* getAllMotif() {
try {
let { detail } = yield select(state => state.user);
const result = yield call(API.getAllMotif, detail.api_token);
yield put({
type: types.GET_ALL_MOTIF_SUCCESS,
payload: result,
});
} catch (err) {
yield put(handleError(err));
yield put({
type: types.GET_ALL_MOTIF_FAILURE,
payload: err,
});
}
}
here my reducer
case types.GET_ALL_MOTIF_SUCCESS:
return {
...state,
motif: [
...action.payload.data.data
]
};
here my request code
internals.process = (method, path, payload, token, contentType=internals.contentType) => {
const request = {
url: `${API_URL}/${path}`,
method: method,
headers: {
'Content-Type': contentType,
'Accept': 'application/json',
},
};
if (token) {
request.params = {
token: token,
};
}
if (payload) {
request.data = payload;
}
return axios.request(request)
.then(res => {
if (![200, 201].includes(res.status)) {
throw new Error(res.status);
}
return res.data;
})
.catch((error) => {
console.error(method, path, error);
return Promise.reject({
message: error.response.data.error,
code: error.response.status
});
});
};
I don't know why in this type get error, because in type kristik also have very similar code.
You didn't dispatch an action that wasn't a plain object, your function getAllMotif not return a plain object. That lead to the error here.
You should dispatch an normal action
getAllMotifAction(token) {
const path = `motif`;
const method = 'get';
return { type: 'GET_ALL_MOTIF', data: { path, method } };
},
Then in in saga, you catch this action and handle it with your saga function
takeLatest('GET_ALL_MOTIF', getAllMotif);

How to convert a CURL request into an axios request?

I just successfully curled here:
curl -X POST https://jenkins-url/job/MyJob/job/some-job/job/master/build --user myemail:mypassword -H 'Jenkins-Crumb: mycrumb'
now I want to use axios inside my lambda
so I have this:
const axios = require('axios')
exports.handler = async (event) => {
const url = "my-url";
try {
const res = await axios.post(url, {}, {
auth: {
username: 'user',
password: 'passowrd'
},
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Jenkins-Crumb": "my-crumb"
},
}).then(function(response) {
console.log('Authenticated');
}).catch(function(error) {
console.log('Error on Authentication');
});
console.log(res)
return {
statusCode: 200,
body: JSON.stringify(res)
}
} catch (e) {
console.log(e)
return {
statusCode: 400,
body: JSON.stringify(e)
}
}
};
but when I trigger the lambda it returns with: failed with the error "Request completed but is not OK"
not sure if I'm doing something wrong somewhere but seems to be everything is correctly mapped from CURL to axios
You have a few issues:
In your .then(...) handler, you are doing a console log, but you aren't returning anything from that function. Therefore, res is going to be undefined.
You're doing a JSON.stringify on res. res would be an axios response, not the response body. Stringifying the axios response is a bad idea, because it contains hefty object references and also circular references. You want res.data to give you the response data.
The error returned from Axios may also contain these heavy objects and circular references. In my experience, you can actually crash node when trying to serialize responses and errors from axios.
Here's how I'd modify your function:
const axios = require('axios')
exports.handler = async (event) => {
const url = "my-url";
try {
const res = await axios.post(url, {}, {
auth: {
username: 'user',
password: 'passowrd'
},
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Jenkins-Crumb": "my-crumb"
},
});
return {
statusCode: 200,
body: JSON.stringify(res.data)
}
} catch (e) {
console.log(e)
return {
statusCode: 400,
// Don't do JSON.stringify(e).
// e.response.data will be the axios response body,
// but e.response may be undefined if the error isn't an HTTP error
body: e.stack
}
}
};

fetch not executing with correct params - React Native

So I have a React Native app, making calls to my own external api via the fetch() native API. I am encountering a strange issue with my requests not being processed by fetch() correctly in only one context.
The calls are supposed to POST to /api/token_login.
Here is how I make my calls in the app:
#/src/services/post.js
import headers from './headers';
const APIURL = '******/api';
export default async (path, data, callback) => {
try {
const postData = {
method: 'POST',
credentials: 'include',
headers: new Headers(headers),
body: JSON.stringify(data)
};
const requestURL = `${APIURL}/${path}`;
const request = new Request(requestURL, postData);
const response = await fetch(request);
const res = await response.text();
if (response.ok) {
callback(null, res);
} else {
const error = res;
callback(error, null);
}
} catch (error) {
console.log('caught error: ', error);
}
};
#/src/services/auth.js
import post from './post';
export function TokenLogin(data, callback) {
post('token_login', data, callback);
}
...other functions
#/src/containers/Login.js
const data = {
user: {
auth_token: token,
},
};
return TokenLogin(data, (err, response) => {
const res = JSON.parse(response);
... do stuff
};
This function gets called on componentDidMount under certain conditions, which is the expected behavior. However, every day or so it suddenly stops sending the request to the passed in path, and sends a GET to /api/login instead. Changing the path passed into the function changes the behavior back to the expected one (i.e., passing in flurgl sends a POST request to .../api/flurgl with the body passed in correctly. Here is some debugging info:
// the logs:
=> Request method: POST url: https://*****/api/token_auth
=> Response object:
=> Response {type: "default", status: 404, ok: false, statusText: undefined, headers: Headers, …}
bodyUsed: true
headers: Headers {map: {…}}
ok: false
status: 404
statusText: undefined
type: "default"
url: "https://*******/api/login"

Categories

Resources