Handling errors on nuxt3 usefetch - vue.js

I just cant figure out how to handle errors here:
const { error, data } = useFetch('https://example.app/api/contact', {
method: "POST",
headers: { "Content-Type": "application/json" },
body: {
name: form.name.value,
email: form.email.value,
message: form.message.value
}
});
console.log(error.value, error)
On error itself it returns ref with _error that contains object with errors. However I cannot get to those errors anyhow..

ref: https://v3.nuxtjs.org/api/composables/use-fetch
useFetch return values {data, pending, error, refresh}, here is an example.
const { data, pending, error, refresh } = await useFetch(
'https://api.nuxtjs.dev/mountains',
{
pick: ['title']
}
)
BTW,useFetch return a Promise, in your example, you can do as follows.
useFetch('https://example.app/api/contact', {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: {
name: form.name.value,
email: form.email.value,
message: form.message.value
}
}).then(res => {
const data = res.data.value
const error = res.error.value
if (error) {
// dealing error
console.log(error)
} else {
console.log(data)
}
}, error => {
console.log('exception...')
console.log(error)
})

Ok, here is a practical solution, you can do the console log after checking error, like this:
if (error.value) {
console.log(error.value)
throw createError({statusCode: 404, statusMessage: "Page
not found.", fatal: true})
}
You do not get error out, why console.log fails, you need to get the value after the error is trigged.

Related

Express can't set headers after they are sent to the client

I have the following code:
router.post('/:email/addWorkflow', async function (req, res, next) {
const params = req.params;
const workflow = req.body;
const email = params.email;
User.findOne({ email: email }, function (err, user) {
if (err) {
res.status(500).send({
error: 'Error while querying database'
});
} else if (user) {
const workflows = user.workflows;
workflows.forEach(wf => {
if (wf) {
if (wf.workflowId === workflow.workflowId) {
res.status(409).send({
error: 'Workflow with that id already exists'
});
}
}
});
workflows.push(workflow);
User.updateOne({ email: email }, { $set: { workflows: workflows } }, { upsert: false }, function (err) {
if (err) {
res.status(500).send({
message: 'Error while updating database'
});
} else {
res.status(200).send({
message: 'Wf added successfully'
});
}
});
} else {
res.status(404).send({
message: 'No such user'
});
}
});
});
After I make a post with an already existing workflowId, I get the following error:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:485:11)
..........
at /home/petar/Documents/jsProjects/p/backend/routes/users.js:50:29
at CoreDocumentArray.forEach (<anonymous>)
at /home/petar/Documents/jsProjects/p/backend/routes/users.js:47:17
at /home/petar/Documents/jsProjects/p/backend/node_modules/mongoose/lib/model.js:4915:16
at /home/petar/Documents/jsProjects/p/backend/node_modules/mongoose/lib/model.js:4915:16
at /home/petar/Documents/jsProjects/linear-mixed-models/backend/node_modules/mongoose/lib/query.js:4380:11
[... lines matching original stack trace ...]
at processTicksAndRejections (internal/process/task_queues.js:76:11) {
code: 'ERR_HTTP_HEADERS_SENT'
Any ideas? I looked at other posts for the same error. I understand that it happens if I try to send response 2 time: res.send({...}) and res.send({...}). However, this does not happen in my case. Thanks in advance
I am not completely sure what line the error message is indicating, but the following loop is the only place I can think of a multiple response on your code
workflows.forEach(wf => {
//foreach is looping
if (wf) {
if (wf.workflowId === workflow.workflowId) {
res.status(409).send({
error: 'Workflow with that id already exists'
});
//but I don't think this guy will stop looping after the first "send()"
}
}
});

Firebase Cloud Functions Call : error : Object message : "Bad Request" status : "INVALID_ARGUMENT"

first of all i am working with react-native
i wanted to use Custom Claims on my project since it seems to fit the role distribution i expect to use on my app.
after setting my app following the documentation i succeed on creating some functions
but, here's the thing, when i try to call a function by fetching the endpoint i always get this error :
in the console
error
:
Object
message
:
"Bad Request"
status
:
"INVALID_ARGUMENT"
in firebase console
addAdminRoleTest Request body is missing data. { email: 'dev#test.com' }
i couldn't find any answer to that except that i send wrong information from my fetch but i don't understand why.
i even tried to simplify my function only to get the data i sent but i had the exact same error
find below my cloud function & the calling method :
functions/index.js
exports.addAdminRole = functions.https.onCall((data, context) => {
// get user
return admin.auth().getUserByEmail(data.email).then(user => {
// if not already (admin)
if(user.customClaims && (user.customClaims).admin === true) {
return;
}
// add custom claim (admin)
return admin.auth().setCustomUserClaims(user.uid, {
admin: true
});
}).then(() => {
return {
message: `Bravo : ${data.email} fait partie de l'équipe Admins`
}
}).catch(err => {
return err;
});
});
simplified function :
exports.addAdminRoleTest = functions.https.onCall(data => {
console.log("parse data : "+JSON.parse(data));
return (
JSON.parse(data)
);
});
adminScreen.js
function httpAddAdminRole() {
const initRequest = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body:JSON.stringify({
email: 'dev#test.com'
})
}
console.log(initRequest);
return fetch('https://us-central1-my-project.cloudfunctions.net/addAdminRole', initRequest)
.catch(err => console.log(err))
.then(res => res.json())
.then(parsedRes => {
console.log(parsedRes);
});
}
in the end this was mostly json knowledge that missed me
my body should have data included
here's the answer i came to :
functions/index.js
exports.addAdminRole = functions.https.onCall((data, context) => {
const dataParsed = JSON.parse(data);
// get user
return admin.auth().getUserByEmail(dataParsed.email).then(user => {
// if not already (admin)
if(user.customClaims && (user.customClaims).admin === true) {
console.log(dataParsed.email + " is already an Admin");
return;
}
// add custom claim (admin)
return admin.auth().setCustomUserClaims(user.uid, {
admin: true
});
}).then(() => {
return {
message: `Bravo : ${dataParsed.email} is now an Admin`
}
}).catch(err => {
return err;
});
});
adminScreen.js
function httpAddAdminRole(mail) {
const initRequest = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body:JSON.stringify({
data:JSON.stringify({
email: mail
})
})
}
console.log(initRequest);
return fetch('https://us-central1-my-project.cloudfunctions.net/addAdminRole', initRequest)
.catch(err => console.log(err))
.then(res => res.json())
.then(parsedRes => {
console.log(parsedRes);
});
}

Catch error server response with #nuxtjs/auth

I'm trying to catch the error response for #nuxtjs/auth but it doesn't seem to return anything but undefined.
It refuses to login if I include the user so I want to know why it's returning undefined.
CONFIG:
auth: {
strategies: {
local: {
endpoints: {
login: {
url: 'http://127.0.0.1:80/api/login',
method: 'post',
propertyName: 'token'
},
logout: false,
user: {
url: 'http://127.0.0.1:80/api/me',
method: 'get',
propertyName: undefined
}
},
tokenRequired: true,
tokenType: 'bearer',
}
},
plugins: [
'#/plugins/auth.js'
]
},
PLUGIN:
export default function ({ app }) {
app.$auth.onError((error, name, endpoint) => {
console.error(name, error)
});
}
VIEW FUNCTION:
- both handleSuccess and handleFailure returns undefined.
login() {
this.toggleProcessing(0);
let payload = {
username: 'admin',
password: 'admin123'
}
let handleSuccess = response => {
console.log(response);
this.toggleProcessing(0);
}
let handleFailure = error => {
console.log(error);
this.toggleProcessing(0);
}
this.$auth.loginWith('local', { data: payload }).then(handleSuccess).catch(handleFailure);
},
You can use e.response
async login() {
try {
const login = {
username: this.username,
password: this.password
}
let response = await this.$auth.loginWith('local', { data: login })
console.log('response', response)
} catch (e) {
console.log('Error Response', e.response)
}
}
I fell into the same problem and after spending some time i found out a very good way to catch the response. The solution is to use the axios interceptor. Just replace your plugin file code with the following
export default function ({$axios, $auth}){
$axios.interceptors.response.use(function (response) {
// Do something with response data
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
}
I'm not sure initially what might be wrong here because I can't see the complete nuxt.config.js and your full component but here are a few things to check:
#nuxtjs/axios is installed
Both axios and auth modules are registered in the modules section of nuxt.config.js:
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth'
]
Also, ensure the middleware property for auth is set in the component/page component.
Ensure you're following the documentation on this page: https://auth.nuxtjs.org/getting-starterd/setup
Ive been using try -> this.$auth.loginWith to catch error server response with #nuxtjs/auth.
login() {
const data = { form };
try {
this.$auth
.loginWith("local", { data: data })
.then(api => {
// response
this.response.success = "Succes";
})
.catch(errors => {
this.response.error = "Wrong username/password";
});
} catch (e) {
this.response.error = e.message;
}
},
Specify the token field in the nuxt.config
strategies: {
local: {
endpoints: {
login: { // loginWith
url: "auth/login",
method: "post",
propertyName: "data.token" // token field
},
user: { // get user data
url: "auth/user",
method: "get",
propertyName: "data.user"
},
}
}
},
modules: ["#nuxtjs/axios", "#nuxtjs/auth"],

AsyncStorage data changing upon app restart

I'm currently calling a JSON api to set an auth token which I'll just be storing in the AsyncStorage to persist between app life so a user doesn't have to log in every single time.
I'm currently setting that token like so:
fetch(url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(this.state)
})
.then( resp => {
return resp.json();
})
.then( async (data) => {
if ('error' in data) {
this.setState({
error: data.error,
password: ''
})
this.secondTextInput.focus();
}
if ('access_token' in data) {
try {
await AsyncStorage.setItem('access_token', data.access_token);
} catch (error) {
return error;
}
this.props.navigation.navigate('Main');
}
})
.catch(
error => {
console.error(error)
return error;
}
);
If I then call AsyncStorage.getItem('access_token') After killing the app or reloading it I'm winding up with this output:
{
"_40":0,
"_65":0,
"_55":null,
"_72":null
}
If I then call AsyncStorage.getItem('access_token') Before killing the app or reloading it I'm winding up with the correct access token. I've double checked the code and I'm not using AsyncStorage.setItem('access_token') anywhere else.
This is how I'm retrieving my token:
componentDidMount() {
console.warn('Mounting');
try {
let token = AsyncStorage.getItem('access_token');
console.warn(token);
if(token !== null) {
console.error(token);
}
} catch (error) {}
AsyncStorage.getItem() is a asynchronous action just like setItem(), so you need to wait until the Promise has been resolved before logging.
Edit
Tip: if you see some strange output like that it is always related to a Promise which is not yet resolved or rejected
I've solved my issue by using #dentemm's recommendation of creating an async function.
async _getToken() {
try {
var token = await AsyncStorage.getItem('access_token');
return token;
} catch(e) {
console.error(e);
}
}
componentDidMount() {
let token = null;
this._getToken()
.then( rsp => {
fetch(global.url + '/api/auth/refresh', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + rsp
}
})
.then(rsp => {
return rsp.json();
})
.then(data => {
if('access_token' in data) {
try {
AsyncStorage.setItem('access_token', data.access_token);
} catch (error) {
return error;
}
this.props.navigation.navigate('Main');
}
})
.catch( error => {
return error;
})
});
}
This way I can get my token from the storage then run my refresh function to get an updated token to use for future requests.

Unhandled promise rejection: Error: Request failed with status code 500

I am trying to call an api and I get the error "Unhandled promise rejection: Error: Request failed with status code 500". I dunno how did I get the error.I put the api call in componentDidMount. I am not sure whether the error comes from the redux implementation or from how I called the api.
This is how I called the api. After a successful login, I put the username as a token and use it to call another api.
state={
username: '',
semcode: [
{}
]
}
componentWillMount() {
AsyncStorage.getItem('Login_token').then((token) => {
console.log('this is coursescreen',token);
let Login_token = token;
this.setState({ username: Login_token });
});
}
componentDidMount(){
this.props.getSemcode(this.state.username);
}
componentWillReceiveProps(nextProps) {
console.log('xx',nextProps);
if (nextProps.semCode != undefined) {
this.setState({ semcode: nextProps.semCode });
}
}
This is how I wrote my action file:
export const getSemcode = (username) => async dispatch => {
let param = {
nomatrik: username,
}
console.log(`${helper.ROOT_URL}/result/GetListOfKodSesiSem`)
let code_res = await
axios.post(`${helper.ROOT_URL}/result/GetListOfKodSesiSem`, param)
console.log(code_res.data);
if (code_res.data.length > 0) {
const { code } = code_res.data;
dispatch({ type: SEMCODE_FETCH_SUCCESS, payload: { semCode: code }});
}
}
This is how I wrote my reducer:
import { SEMCODE_FETCH_SUCCESS} from '../actions/types';
const INITIAL_STATE={
semCode:[],
}
export default function (state=INITIAL_STATE, action){
switch(action.type){
case SEMCODE_FETCH_SUCCESS:
return action.payload
default:
return state;
}
}
Can anyone help me pleaseeeeee
Error Message
Error received from axios.post: {"config":{"transformRequest":
{},"transformResponse":{},"timeout":0,"xsrfCookieName":"XSRF-
TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","maxContentLength":-1,"headers":
{"Accept":"application/json, text/plain, /","Content-
Type":"application/json;charset=utf-8"},
"method":"post","nomatrik":"BB16160907",
"url":"https://smp.ums.edu.my/api/result/GetListOfKodSesiSem","data":"
{\"Accept\":\"application/json\",\"Content-
Type\":\"application/json\"}"},"request":
{"UNSENT":0,"OPENED":1,"HEADERS_RECEIVED":2,"LOADING":3,"DONE":4,
"readyState":4,"status":500,"timeout":0,"withCredentials":true,"upload":
{},"_aborted":false,"_hasError":false,"_method":"POST","_response":"
{\"Message\":\"An error has occurred.\"}",
"_url":"https://smp.ums.edu.my/api/result/GetListOfKodSesiSem",
"_timedOut":false,"_trackingName":"unknown",
"_incrementalEvents":false,"responseHeaders":{"Date":"Sat, 30 Dec 2017
03:58:25
GMT","Content-Length":"36","X-Powered-By":"ARR/3.0","X-AspNet-
Version":"4.0.30319","Expires":"-1","Content-Type":"application/json;
charset=utf-8","Server":"Microsoft-IIS/10.0","Pragma":"no-cache","Cache-
Control":"no-cache"},"_requestId":null,"_headers":
{"accept":"application/json, text/plain, /","content-
type":"application/json;charset=utf-
8"},"_responseType":"","_sent":true,"_lowerCaseResponseHeaders":{"date":"Sat,
30 Dec 2017 03:58:25
GMT","content-length":"36","x-powered-by":"ARR/3.0","x-
aspnet-version":"4.0.30319","expires":"-1","content-type":"application/json; charset=utf-8","server":"Microsoft-IIS/10.0","pragma":"no-cache","cache-
control":"no-cache"},"_subscriptions":[],"responseURL":
"https://smp.ums.edu.my/api/result/GetListOfKodSesiSem"},"response":{"data":
{"Message":"An error has
occurred."},"status":500,"headers":{"date":"Sat, 30 Dec 2017 03:58:25
GMT","content-length":"36","x-powered-by":"ARR/3.0","x-
aspnet-version":"4.0.30319","expires":"-1","content-type":"application/json; charset=utf-8","server":"Microsoft-IIS/10.0","pragma":"no-cache","cache-
control":"no-cache"},"config":{"transformRequest":{},"transformResponse":
{},"timeout":0,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-
TOKEN","maxContentLength":-1,"headers":{"Accept":"application/json,
text/plain,
/","Content-Type":"application/json;charset=utf-8"},"method": "post","nomatrik":"BB16160907",
"url":"https://smp.ums.edu.my/api/result/GetListOfKodSesiSem","data":"
{\"Accept\":\"application/json\",\"Content-
Type\":\"application/json\"}"},"request":
{"UNSENT":0,"OPENED":1,"HEADERS_RECEIVED":2,"LOADING":3,"DONE":4,
"readyState":4,"status":500,"timeout":0,"withCredentials":true,"upload":
{},"_aborted":false,"_hasError":false,"_method":"POST","_response":"
{\"Message\":\"An error has occurred.\"}",
"_url":"https://smp.ums.edu.my/api/result/GetListOfKodSesiSem",
"_timedOut":false,"_trackingName":"unknown","_incrementalEvents":false, "responseHeaders":{"Date":"Sat, 30 Dec 2017 03:58:25 GMT","Content-
Length":"36","X-Powered-By":"ARR/3.0","X-AspNet-
Version":"4.0.30319","Expires":"-1","Content-Type":"application/json;
charset=utf-8","Server":"Microsoft-IIS/10.0","Pragma":"no-cache","Cache-
Control":"no-cache"},"_requestId":null,"_headers":
{"accept":"application/json, text/plain, /","content-
type":"application/json;charset=utf-
8"},"_responseType":"","_sent":true,"_lowerCaseResponseHeaders":{"date":"Sat,
30 Dec 2017 03:58:25
GMT","content-length":"36","x-powered-by":"ARR/3.0","x-
aspnet-version":"4.0.30319","expires":"-1","content-type":"application/json; charset=utf-8","server":"Microsoft-IIS/10.0","pragma":"no-cache","cache-
control":"no-cache"},"_subscriptions":
[],"responseURL":"https://smp.ums.edu.my/api/result/GetListOfKodSesiSem"}}}
Login action:
export const attemptLogin = (username, password) => async dispatch => {
let param = {
txtNomatrik: username,
txtPwd: password,
public_key: helper.PUBLIC_KEY,
secret_key: helper.SECRET_KEY
}
console.log(`${helper.ROOT_API_URL}/v1/basic/ad/std/login`)
let login_res = await
axios.post(`${helper.ROOT_API_URL}/v1/basic/ad/std/login`, param)
console.log(login_res.data);
await AsyncStorage.setItem('jwtToken',login_res.data.token);
if (login_res.data.status == 'Successful login') {
const { login } = login_res.data;
dispatch({ type: LOGIN_SUCCESS});
}
}
Problem
Your request is failing because you are not adding the JWT token to the headers.
Solution
Using Axios and with your code this should work. Evidently our big problem here was that you have to pass data even though it is empty. If we do not pass data it fails with error 500.
export const getSemcode = (username) => async dispatch => {
let jwtToken = await AsyncStorage.getItem('jwtToken').then((data) => {
console.log('this is semcode',data);
});
let config = {
method: 'POST',
url: 'url/to/sem',
headers: {
'content-type': 'application/x-www-form-urlencoded',
AntiTemperSignature: jwtToken,
UserID: '123456',
},
data: '',
json: true
};
try {
return axios(config)
.then((response) => {
console.log(response);
if (response.data.length > 0) {
const { code } = response.data;
dispatch({ type: SEMCODE_FETCH_SUCCESS, payload: { semCode: code } });
}
})
.catch((error) => {
console.log(error);
});
}
}
You are looking in the wrong place.
An error code 500 is returned by the remote server when it can't handle the request. In this case, I suspect that the POST to ${helper.ROOT_URL}/result/GetListOfKodSesiSem is failing. The axios library is a promise based library. Wrap the call in a try-catch block like this:
try {
console.log(`${helper.ROOT_URL}/result/GetListOfKodSesiSem`)
let code_res = await
axios.post(`${helper.ROOT_URL}/result/GetListOfKodSesiSem`, param)
console.log(code_res.data);
if (code_res.data.length > 0) {
const { code } = code_res.data;
dispatch({ type: SEMCODE_FETCH_SUCCESS, payload: { semCode: code }});
}
} catch (err) {
console.error(`Error received from axios.post: ${JSON.stringify(err)}`);
}
This will at least give you a view in your debug console on what is happening. You can then coordinate that call with any debug logs from the backend to figure out what the error really is.
Your root cause, however, is that the remote server is returning a Server Error (HTTP code 500) to your client.