Request failed with status code 401', name: 'AxiosError', code: 'ERR_BAD_REQUEST' - vue.js

I'm on a page that uses a vue component and one of my patch routes is saying I'm un-authenticated.
<template>
...
<button #click="editPost(attributes.attributes.post_id)"></button>
...
</template>
<script>
export default {
data() {
return {
info: null,
message: null,
postTitle: "",
postContent: ""
}
},
methods: {
editPost(id) { // not working, 401 unauthenticated
console.log('edit post clicked', id);
axios.patch('http://127.0.0.1:8000/api/posts/' + id, {
headers: {
Authorization: 'Bearer 3d58d6cd66e134a59b3a9373a2b4a233e55d00107b9251f654c5c92a2276a1c5'
}
})
.then((response) => {
this.info = response.data;
// this.message = 'Success';
console.log(this.info);
})
.catch((error) => {
console.log(error, error.response.data.message);
this.message = error.response.data.message;
})
},
deletePost(value){
console.log('delete post clicked', value);
}
},
mounted() {
axios.get('http://127.0.0.1:8000/api/posts', { // working as expected, authenticated
headers: {
Authorization: 'Bearer 3d58d6cd66e134a59b3a9373a2b4a233e55d00107b9251f654c5c92a2276a1c5'
}
})
.then((response) => {
this.info = response.data;
this.message = 'Success';
console.log(this.info);
})
.catch((error) => {
console.log(error, error.response.data.message);
this.message = error.response.data.message;
})
}
}
</script>
I dont understand how this can be since I have to authenticate to get the posts on page load and they load fine, with authentication using a Bearer token in header?
Why is the call to axios using a PATCH not working? The PATCH call works in postman fine also.

Related

Vue API data is gone on window refresh

When I login I am redirected to secret page which needs JWT authentication. Data is loaded on secret page. And when I refresh the window - data is lost. How can I fix it?
I use eventBus to send a JWT token to sibling template.
Login view method on submit:
submitSignin() {
console.log("submit!");
this.submitted = true;
this.$v.$touch();
if (this.$v.$invalid) {
return; // stop here if form is invalid
}
axios
.post("http://localhost:3000/auth/login", this.authData)
.then((res) => {
this.token = res.data.token;
this.authData.email = "";
this.authData.password = "";
this.$v.$reset();
this.successMsg = "You Sign in Successfully!";
this.$router.push({ path: "/auth/all-users" });
this.$nextTick(() => {
eventBus.$emit("sendtoken", this.token);
});
})
.catch((err) => {
console.log(err.response.data.message);
this.errorMsg = err.response.data.message;
});
},
SecretPage view:
<script>
export default {
name: "SecretPage",
data() {
return {
users: [],
};
},
methods: {
loadUsers() {
let self = this;
eventBus.$on("sendtoken", (token) => {
axios
.get("http://localhost:3000/auth/all-users", {
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((response) => {
console.log(token);
console.log(response.data.users);
self.users = response.data.users;
})
.catch((err) => {
console.log(err);
});
});
},
},
mounted() {
this.loadUsers();
},
};
</script>
loaded users

Proper way to extract the code from Vue Store to Login.vue page

I want to know what part of code I should extra from the store and add in Login.vue
And how can I throw the validations errors return from API in Store so that I can handle them in Login.vue page
Login.vue
<template>My login form is here</template>
<script>
import { AUTH_AUTHENTICATE } from "#/modules/auth/store/index";
methods: {
loginFormSubmit() {
/** AFTER LOGIN SUCCESS FROM STORE,
WHAT CAN I HANDLE HERE SO THAT MY STORE IS CLEAN
*/
this.$store.dispatch(AUTH_AUTHENTICATE, this.loginForm);
}
}
</script>
src/modules/auth/store/index
export const AUTH_AUTHENTICATE = "/api/auth/authenticate";
actions: {
[AUTH_AUTHENTICATE]: ({ commit }, loginForm) => {
toolsApi.get("/sanctum/csrf-cookie").then(() => {
toolsApi
.post("/api/auth/authenticate", loginForm)
.then(response => {
if (response.data.status == "success") {
const token = `Bearer ${response.data.data.token}`;
Cookie.set("AUTH-TOKEN", token);
toolsApi.defaults.headers.common.Authorization = Cookie.get(
"AUTH-TOKEN"
);
commit("loginStatus", true);
this.$router.push({ name: "dashboard.index" });
}
})
.catch(error => {
console.log("Error");
console.log(error);
});
});
}
}
Any guidance on correction of my code will really help me a lot
/**** UPDATE ***/
Error response from API
{
"status": "error",
"message": "Validation errors.",
"errors": {
"email": [
"The email field is required."
],
"password": [
"The password field is required."
]
}
}
In Store
toolsApi
.post("/api/auth/authenticate", loginForm)
.then(response => {
if (response.data.status == "success") {
const token = `Bearer ${response.data.data.token}`;
Cookie.set("AUTH-TOKEN", token);
toolsApi.defaults.headers.common.Authorization = Cookie.get(
"AUTH-TOKEN"
);
commit("setLoginStatus", true);
resolve(response.data.data);
// this.$router.push({ name: "dashboard.index" });
}
})
.catch(error => {
reject(error);
});
Try to return toolsApi.get(...) from [AUTH_AUTHENTICATE] action, then access it like Promise. Another way to throw exception in action and catch it in login page.

How to fetch data in Vue 3?

I don't know how to fetch data with Vue 3? I created one action and with this action I am calling endpoint (https://api.openbrewerydb.org/breweries/5494). I didn't get response data.
Endpoint:
import { createStore } from 'vuex'
export default createStore({
state: {
},
mutations: {
},
actions: {
async getData() {
await fetch('https://api.openbrewerydb.org/breweries/5494', {
method: 'get',
headers: { 'Content-type': 'application/json' },
}).then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
console.log('response: ', response)
}).catch((error) => {
console.log('Looks like there was a problem: \n', error);
});
}
},
modules: {
}
})
Vue component:
<template>
<div #click="loadData">Load Data</div>
</template>
<script>
import { useStore } from 'vuex'
export default {
name: 'HelloWorld',
props: {
msg: String
},
setup () {
const store = useStore()
const loadData = () => {
store.dispatch('getData')
}
return { loadData }
}
}
</script>
As a response I didn't get anything but I should get:
{"id":5494,"name":"MadTree Brewing","brewery_type":"regional","street":"3301 Madison Rd","address_2":null,"address_3":null,"city":"Cincinnati","state":"Ohio","county_province":null,"postal_code":"45209-1132","country":"United States","longitude":"-84.4239715","latitude":"39.1563725","phone":"5138368733","website_url":"http://www.madtreebrewing.com","updated_at":"2018-08-24T15:44:22.281Z","created_at":"2018-07-24T01:34:01.620Z"}
You need to make the data to json
.then(res=>res.json())
this will do the trick for you.
const getData = () => {
fetch('https://api.openbrewerydb.org/breweries/5494', {
headers: { 'Content-type': 'application/json' },
}).then(res=>res.json()).then((response) => {
console.log({ response })
}).catch((error) => {
console.log('Looks like there was a problem: \n', error);
});
}
getData();
If the response fails, it will surely get you to catch.
This answer Should be the accepted answer.
If readers landed here while working through the introductory examples on the Vue.js website, Adarsh's code can be adapted thusly (for Vue.js 3):
<div id="beer">
{{ message }}
</div>
const Breweries = {
data() {
return {
message: ""
}},
mounted() {
fetch('https://api.openbrewerydb.org/breweries/', {
headers: { 'Content-type': 'application/json' },
}).then(res=>res.json()).then((response) => {
this.message = response;
}).catch( (error) => {
this.message = error;
});
}
}
Vue.createApp(Breweries).mount('#beer')
First you must install a package like axios
Then create an object from axios and call the API
import axios from "axios";
export default {
setup() {
function getUsers() {
axios.get("https://jsonplaceholder.typicode.com/users")
.then(function (response) {
// handle success
console.log(response.data);
})
.catch(function (error) {
// handle error
console.log(error);
});
getUsers();
}
return { getUsers };
},
};

How to add header to get request in vue js?

I am taking data from api, how to send get request with token after login?
It shows error createError.js?2d83:16 Uncaught (in promise) Error: Request failed with status code 401
export default new Vuex.Store({
state: {
users: []
},
mutations: {
setUsers(state, args){
state.users = args;
}
},
actions: {
login({ }, arg) {
axios.post('login/', { username: arg.username, password: arg.password })
.then((response) => {
console.log(response);
let accessToken = response.token.data;
localStorage.setItem('token', accessToken);
localStorage.setItem('user', response.data.user);
axios.defaults.headers.common['Authorization'] = accessToken;
window.isSignedIn = true;
router.push('/');
})
.catch((error) => {
console.log(error);
})
},
getUsers({ commit }){
let { data } = axios.get('v1/user/list/');
commit('setUsers', data);
}
}
})
Depends which authentication you are using. Try with:
axios.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`;
Other HTTP authentication schemes.

How to update view inside axios promise and after store dispatch?

I have a simple vue app where I'm trying to add simple authentication. Inside my login.vue, I use axios to authenticate the user via ajax and store the token returned by the api in the store then redirect to a new page (ex: dashboard.vue).
The problem is that the token is saved but the view is not updated, can't call router.push() ...
Any ideas why isn't it working ? Thanks
Login.vue
methods: {
authenticate () {
var dataLogin = {
email: this.login,
password: this.password
}
var headers = { headers: { 'Content-type': 'application/json', 'Accept': 'application/json' } }
axios.post(config.apiUrl, dataLogin, headers)
.then(response => {
this.$store.dispatch('login', response.data).then(() => {
// if there is no error go to home page
if (!this.$store.getters.error) {
this.$router.push('/')
}
})
})
.catch(error => {
this.errorMessage = error.response.data.message
this.authError = true
})
}
}
The store function just save the token with localStorage
const actions = {
login (context, data) {
context.commit('authenticate', data)
}
}
const mutations = {
authenticate (state, data) {
localStorage.setItem('user-access_token', data.access_token)
}
}
You are calling a then() handler when you dispatch the action.
But your action does not return a promise.
So return a promise in your action as follows:
const actions = {
login (context, data) {
return new Promise((resolve, reject) => {
context.commit('authenticate', data)
resolve()
})
}
}
Also chain your promises for better readability
axios.post(config.apiUrl, dataLogin, headers)
.then(response => {
return this.$store.dispatch('login', response.data)
}).then(() => {
// if there is no error go to home page
if (!this.$store.getters.error) {
this.$router.push('/')
}
})
.catch(error => {
this.errorMessage = error.response.data.message
this.authError = true
})