is a bit of a situation
after simple login
i'v tried to properly handle the server error response but at first i thought it will be simple. i was wrong.
the press login function rely on the login function to pass the login status to check if the user is or not logged.
in a way the code works but it will be great if can get the server response and display.
i've tried to use catch or get a response from the login function. either way still not getting the responde. please someone could spare a hint related to this of problem?
login handler on login.jsx
pressLogin() {
return auth
.login(this.state.email, this.state.password)
.then(response => {
this.props.updateAuth();
let res = response.text();
if (response.login_status == false) {
let errors = res;
throw response.json();
//this.setState({ error: errors });
} else {
// console.log('asdasd')
// this.forceUpdate();
this.setState({ redirectToHome: true });
}
})
.catch(errors => {
return errors;
console.log("Error");
});
}
}
if i set a state in catch just setting a string works but it will be great if can get the server side errors
the login on auth.js
login(email, password) {
return fetch("/login", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
email: email,
password: password
})
})
.then(resp => {
if (resp.status >= 200 && resp.status < 300) {
return resp.text();
} else {
throw resp.json();
}
})
.then(response => {
if (!response.status) {
window.localStorage.setItem("auth_token", response);
return {
login_status: true
};
} else {
return {
login_status: false
};
}
})
.catch(error => {
console.log("Error" + error);
return {
login_status: false
};
});
},
Related
I have already define error initially, but now I don't know why show me error like this
fetch data from backend code:
auth.js file
import fetch from "isomorphic-fetch";
import { API } from "../config";
export const signup = (user) => {
return fetch(`${API}/signup`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(user),
})
.then((res) => {
return res.json();
})
.catch((err) => {
console.log(err);
});
};
I have link connection inside API I'm sure is it ok.
After that when i submit my signup from then show me error, signup handleSubmit code:
signupComponent.js file
const handleSubmit = (e) => {
e.preventDefault();
//console.table({ name, email, password, error, loading, message, showForm });
setValues({ ...values, loading: true, error: false });
const user = { name, email, password };
signup(user).then((data) => {
try {
if (data.error) {
setValues({ ...values, error: data.error, loading: false });
} else {
setValues({
...values,
name: "",
email: "",
password: "",
error: "",
loading: false,
message: data.message,
showForm: false,
});
}
} catch (err) {
console.log(err);
}
});
};
I'm sure my internet connection is ok.
I don't know where is problem.
Any suggestion please.
auth.js file updated:
Return the err from catch
import fetch from "isomorphic-fetch";
import { API } from "../config";
export const signup = (user) => {
return fetch(`${API}/signup`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(user),
})
.then((res) => {
return res.json();
})
.catch((err) => {
return err;
});
};
You have a chain of callbacks
fetch().then().catch()
in your .then() you return the data but in your .catch() you return nothing.
Therefore your outer chain will try to process undefined incase the fetching failed.
signup().then(
(data) => ... data.error // data is undefined
)
I have solve my problem by this way:
used try catch block for find problem
In the catch block used .catch((err) => { return err; });
And make sure API connected succesfully
After that run my backend server
Then run my frontend.
First off this was working before but when I opened the code for further change to add redux it stopped working.
I am Sending the login Request from Axios to backend API . But when I click on submit button It does not seem to work. Even it does not print the console.log("I am in ") statement. But when I got to the network tab and see the xhr , I see the output attached in image. Last day it was working all of fine. But Now I am getting no response and even not a console statement to see if I am going in Submit form function.
Here Is my code SignIn.js
let submitForm = (e) => {
e.preventDefault();
console.log("I am in "); //button click not printing this statement but axios request is made
let loginDataObject = {
email: formDetails.userEmail,
password: encryptThis(formDetails.LoginPassword)
}
// Axios request
const url = 'http://localhost:5000/api/v1/users/login'
axios({
method: 'post',
url: url,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
data: loginDataObject
})
.then(res => {
const status = res.status;
const userEmail = res.data.data.user.email;
if (status === 200) {
let userObject = {
email: JSON.stringify(userEmail),
tk: JSON.stringify(res.data.token)
}
localStorage.setItem('currentUser', JSON.stringify(userObject));
}
})
.then(() => {
history.push('/dashboard')
})
.catch(err => {
// if password is incorrect
console.log(err);
})
}
return (
<input type="button" onClick={submitForm} className="btn btn-primary mainGreenBtnFullWidth" value="Log In" />
)
```
Most probably it is a network-related error. Based on the console log, it looks like your request doesn't reach the server and you don't have a response to check in your code. You could get similar errors because of a CORS error or DNS misconfigurations.
To catch these kinds of errors, since you don't have a response, you can write an Axios interceptor like this:
axios.interceptors.response.use(
(response) => {
return response;
},
(error) => {
if (typeof error.response === "undefined") {
console.log("network error");
window.location.href = "/error-page";
}
if (error.response.status === 401) {
// Authorization error
window.location.href = "/signin";
} else if (error.response.status === 500) {
// Server error
window.location.href = "/500-error";
} else {
return Promise.reject(error);
}
}
);
Of course, this doesn't solve your actual problem, but you can improve the user experience by showing some kind of error.
I am making a request to the server and if I get an error, I want to console.log it but returns a javascript error instead.
I found this solution online where in my interception I can return the error appropriately but seem not to work.
Axios.interceptors.response.use(
response => {
return response;
},
function(error) {
// Do something with response error
if (error.response.status === 401) {
console.log("unauthorized, logging out ...");
store.commit("logout");
router.push({ path: "/login" });
}
return Promise.reject(error.response);
}
);
This is my request:
Axios.put("/api/auth/request/phone/verify", {
phone: this.registeredPhone,
code: this.stashedCode()
})
.then(response => {
console.log(response);
if (response.data.status == 200 && response.data.success) {
swal("Success", response.data.data.message, "success");
}
})
.catch(error => {
// console.log(error);
console.log(error.response);
});
Am expecting something like:
{
"status": 422,
"success": false,
"data": {
"erro": "validation.phone_field_required."
}
but I end up getting: PUT http://localhost:3000/api/auth/request/phone/verify 422 (Unprocessable Entity)
as mentioned in Axios Documents. you should pass valid status code as option to axios. if you dont do that the status code 4XX is an error so it handle by catch block.
axios.get('/user/12345', {
validateStatus: function (status) {
return status < 500; // Reject only if the status code is greater than or equal to 500
}
})
so your request wil be change like this:
axios({
method: 'put',
url: '/api/auth/request/phone/verify',
data: {
phone: this.registeredPhone,
code: this.stashedCode()
},
validateStatus: (status) => {
return status < 500;
},
}).catch(error => {
}).then(response => {
console.log(response);
if (response.data.status == 200 && response.data.success) {
swal("Success", response.data.data.message, "success");
}
})
feel free to ask more question in comments
I'm doing requests to my API server to authenticate a user, that's not the problem. The problem is that I don't know why my async function doesn't return anything, and I get an error because the data that I want from this function is undefined.
Don't worry if the error management is ugly and in general I can do this better, I'll do that after fixing this problem.
Utils.js class
async Auth(username, password) {
const body = {
username: username,
password: password
};
let req_uuid = '';
await this.setupUUID()
.then((uuid) => {
req_uuid = uuid;
})
.catch((e) => {
console.error(e);
});
let jwtData = {
"req_uuid": req_uuid,
"origin": "launcher",
"scope": "ec_auth"
};
console.log(req_uuid);
let jwtToken = jwt.sign(jwtData, 'lulz');
await fetch('http://api.myapi.cc/authenticate', {
method: 'POST',
headers: { "Content-Type": "application/json", "identify": jwtToken },
body: JSON.stringify(body),
})
.then((res) => {
// console.log(res);
// If the status is OK (200) get the json data of the response containing the token and return it
if (res.status == 200) {
res.json()
.then((data) => {
return Promise.resolve(data);
});
// If the response status is 401 return an error containing the error code and message
} else if (res.status == 401) {
res.json()
.then((data) => {
console.log(data.message);
});
throw ({ code: 401, msg: 'Wrong username or password' });
// If the response status is 400 (Bad Request) display unknown error message (this sould never happen)
} else if (res.status == 400) {
throw ({ code: 400, msg: 'Unknown error, contact support for help. \nError code: 400' });
}
})
// If there's an error with the fetch request itself then display a dialog box with the error message
.catch((error) => {
// If it's a "normal" error, so it has a code, don't put inside a new error object
if(error.code) {
return Promise.reject(error);
} else {
return Promise.reject({ code: 'critical', msg: error });
}
});
}
Main.js file
utils.Auth('user123', 'admin')
.then((res) => {
console.log(res); // undefined
});
Your Async function must return the last promise:
return fetch('http://api.myapi.cc/authenticate', ...);
or await the result and return it:
var x = await fetch('http://api.myapi.cc/authenticate', ...);
// do something with x and...
return x;
Notice that you don’t need to mix promise syntax (.then) with await. You can, but you don’t need to, and probably shouldn’t.
These two functions do exactly the same thing:
function a() {
return functionReturningPromise().then(function (result) {
return result + 1;
});
}
async function b() {
return (await functionReturningPromise()) + 1;
}
await is not to be used with then.
let data = await this.setupUUID();
or
let data=null;
setupUUID().then(res=> data = res)
I would try something like this:
const postReq = async (jwtToken) => {
const body = {
username: username,
password: password,
};
try {
const res = await fetch('http://api.myapi.cc/authenticate', {
method: 'POST',
headers: { "Content-Type": "application/json", "identify": jwtToken },
body: JSON.stringify(body),
})
if (res) {
if (res.status == 200) {
return res.json();
} else if (res.status == 401) {
const data = res.json();
console.log(data.message)
throw ({ code: 401, msg: 'Wrong username or password' });
} else if (res.status == 400) {
throw ({ code: 400, msg: 'Unknown error, contact support for help. \nError code: 400' });
}
}
} catch (err) {
console.error(err)
}
};
const Auth = async (username, password) => {
const jwtData = {
"origin": "launcher",
"scope": "ec_auth"
};
try {
const req_uuid = await this.setupUUID();
if (req_uuid) {
jwtData["req_uuid"] = req_uuid;
const jwtToken = jwt.sign(jwtData, 'lulz');
return await postReq(jwtToken);
}
} catch (err) {
console.error(err);
};
}
I'm using Nuxt-axios module with the proxy.
For Error handling, I have common code in
Plugins/axios.js
export default function({ $axios, __isRetryRequest, store, app, redirect , payload , next}) {
$axios.onRequest(config => {
if (app.$cookies.get('at') && app.$cookies.get('rt') && config.url != '/post_login/') {
config.headers.common['Authorization'] = `Bearer ${app.$cookies.get('at')}`;
}
});
$axios.onResponseError(err => {
const code = parseInt(err.response && err.response.status)
let originalRequest = err.config;
if (code === 401) {
originalRequest.__isRetryRequest = true;
store
.dispatch('LOGIN', { grant_type: 'refresh_token', refresh_token: app.$cookies.get('rt')})
.then(res => {
originalRequest.headers['Authorization'] = 'Bearer ' + app.$cookies.get('at');
return app.$axios(originalRequest);
})
.catch(error => {
console.log(error);
});
}
// code for 422 error
if (code == 422) {
throw err.response;
}
});
}
On my page folder index page
Pages/index.vue
<template>
<section>Component data</section>
</template>
<script type="text/javascript">
export default {
async asyncData({ route, store }) {
await store.dispatch('GET_BANNERS');
}
}
</script>
All the API calls are in a stroes/actions.js file.
Now the question is when I refresh the page index.vue first API request will hit and get the response if successful. But now if on first request( 'GET_BANNERS' ) from asyncData and it gets 401 error unauthorized then I'm getting below error
Error: Request failed with status code 401
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
how can I resolve this?
few more questions:
1) When I'm writing common error code in axios, original request on which I have received 401 how can I set data to store again(which we normally do from actions file)?
2) can anyone help with best practice to attach authorization headers and error handle for 400,401,422, etc..
$axios.onResponseError(err => {
const code = parseInt(err.response && err.response.status);
let originalRequest = err.config;
if (code == 401) {
originalRequest.__isRetryRequest = true;
let token = app.$cookies.get('rt');
return new Promise((resolve, reject) => {
let req = $axios
.post(`/login`, { grant_type: 'refresh_token', refresh_token: token })
.then(response => {
if (response.status == 200) {
app.$cookies.set('access', response.data.access_token);
app.$cookies.set('refresh', response.data.refresh_token);
originalRequest.headers['Authorization'] = `Bearer ${
response.data.access_token
}`;
}
resolve(response);
}).catch(e => {
reject("some message");
})
})
.then(res => {
return $axios(originalRequest);
}).catch(e => {
app.router.push('/login');
});
}
});
#canet-robern hope this will solve your prob!!
The error ERR_HTTP_HEADERS_SENT means that you have a bug in your server-side code - hence the error from this bug comes before the HTTP headers.
To handle 4xx errors and retry the Axios request - follow this example:
Vue.prototype.$axios = axios.create(
{
headers:
{
'Content-Type': 'application/json',
},
baseURL: process.env.API_URL
}
);
Vue.prototype.$axios.interceptors.request.use(
config =>
{
events.$emit('show_spin');
let token = getTokenID();
if(token && token.length) config.headers['Authorization'] = token;
return config;
},
error =>
{
events.$emit('hide_spin');
if (error.status === 401) VueRouter.push('/login');
else throw error;
}
);
Vue.prototype.$axios.interceptors.response.use(
response =>
{
events.$emit('hide_spin');
return response;
},
error =>
{
events.$emit('hide_spin');
return new Promise(function(resolve,reject)
{
if (error.config && error.response && error.response.status === 401 && !error.config.__isRetry)
{
myVue.refreshToken(function()
{
error.config.__isRetry = true;
error.config.headers['Authorization'] = getTokenID();
myVue.$axios(error.config).then(resolve,reject);
},function(flag) // true = invalid session, false = something else
{
if(process.env.NODE_ENV === 'development') console.log('Could not refresh token');
if(getUserID()) myVue.showFailed('Could not refresh the Authorization Token');
reject(flag);
});
}
else throw error;
});
}
);