Vue Resource (GET) not sending headers - vue.js

I know about Axios, but I am trying to do this with Vue Resource.
Everything is working fine but is not sending the headers.
No matter what I do, it won't send the headers.
However, when I execute the query and resend it with Firefox console (after adding the auth header) it does work.
But when executing directly from Vue it does not send the header.
When I try to do the exact same thing in Postman, it does work :)
Question: Does anyone know how to solve this?
this.$http.get('https://myapi.com/v1/whatever/option', {
params: {
},
headers: {
'Authorization' : 'Bearer Cd34dfhnc4jn-39q84cq9-pwncpqw349fn83q47903qpnf98nghwehj5UiDXyC:$2y$1gerg34cqw4yas4yqOHAyLk4wy2OkDvxH6HOs.CgocO2TE9Te'
}
}).then(response => {
//console.log(response);
}, response => {
console.log('error:');
console.log(response.headers.get('Authorization'));
console.log(response);
})
P.S. I just tried Axios, and the same problem here... when I check my request, my added headers are NOT there!?
Download my FF Console screenshot
In my Vue file I have a #click event:
this.$http.get('https://boinu.nl/v1/synonyms/autos', {
// params: {
//
// },
// headers: {
// 'Authorization' : 'Bearer CdcmXCj0pdaM7UH6zpWVRSyncWJHhShHPKzvj4wWxNaxIn54LGQMaVU7ihUiDXyC:$2y$10$26IZut5mWqtECbhVIFnSqOHAyLk4wy2OkDvxH6HOs.CgocO2TE9Te'
// }
}).then(response => {
//console.log(response);
}, response => {
console.log('error:');
console.log(response);
})
and in my main.js I have:
import Vue from 'vue'
import App from './App.vue'
import VueResource from 'vue-resource'
Vue.use(VueResource);
new Vue({
el: '#app',
render: h => h(App)
});

Related

How to fix vue axios CORS issue?

How can I prevent CORS issue with vue axios?
Following is the code for making requests with the backend using vue and axios.
axios.config.js
/// here I'm creating a vue axios instance.
import axios from "axios";
export default axios.create({
baseURL: "https://example.com/api/v1/",
headers: {
Accept: "application/json",
Authorization: "TOKEN 3413413dfdsfsafd3rr41",
},
});
and inside the vue.config.js
I've proxied the request.
module.exports = {
devServer: {
proxy: {
"/api/*": {
target: "http://localhost:8081",
secure: false,
changeOrigin: true,
},
},
},
};
and inside my vuex store I'm calling an action:
import axios from 'axios.config'
actions: {
getData({ commit }) {
axios
.get(`products/grocery`)
.then((res) => {
console.log("res :", res);
commit("SET_DATA", res.data);
})
.catch((e) => {
console.log("e :", e);
commit("SET_ERROR", e);
});
},
}
But when I look at the request in the console, I can see that it is sending request to the original url https://example.com/api/v1/ rather than appending the dev server line this: http://localhost:8081/api/v1/
Not sure why the proxying is not working!
External URLs doesn't get proxied. Change the base URL in axios to /api/v1/
export default axios.create({
baseURL: "/api/v1/",
headers: {
Accept: "application/json",
Authorization: "TOKEN 3413413dfdsfsafd3rr41",
},
});
Nuxt provides a proxy option which you can use to avoid cors errors,
Nuxt Documentation
You can refer this for more information and available options #nuxt/proxy

Using axios instance with vuex

I am building a Vue frontend with Rails backend.
On frontend I am using Axios and I have set these interceptors for authentication:
import axios from 'axios'
const API_URL = 'http://localhost:3000'
const securedAxiosInstance = axios.create({
baseURL: API_URL,
withCredentials: true,
headers: {
'Content-Type': 'application/json'
}
})
const plainAxiosInstance = axios.create({
baseURL: API_URL,
withCredentials: true,
headers: {
'Content-Type': 'application/json'
}
})
securedAxiosInstance.interceptors.request.use(config => {
const method = config.method.toUpperCase()
if (method !== 'OPTIONS' && method !== 'GET') {
config.headers = {
...config.headers,
'X-CSRF-TOKEN': localStorage.csrf
}
}
return config
})
securedAxiosInstance.interceptors.response.use(null, error => {
if (error.response && error.response.config && error.response.status === 401) {
// If 401 by expired access cookie, we do a refresh request
return plainAxiosInstance.post('/refresh', {}, { headers: { 'X-CSRF-TOKEN': localStorage.csrf } })
.then(response => {
localStorage.csrf = response.data.csrf
localStorage.signedIn = true
// After another successfull refresh - repeat original request
let retryConfig = error.response.config
retryConfig.headers['X-CSRF-TOKEN'] = localStorage.csrf
return plainAxiosInstance.request(retryConfig)
}).catch(error => {
delete localStorage.csrf
delete localStorage.signedIn
// redirect to signin if refresh fails
location.replace('/')
return Promise.reject(error)
})
} else {
return Promise.reject(error)
}
})
export { securedAxiosInstance, plainAxiosInstance }
On main.js I am making them available this way:
import VueAxios from 'vue-axios'
import { securedAxiosInstance, plainAxiosInstance } from './axios'
Vue.use(VueAxios, {
secured: securedAxiosInstance,
plain: plainAxiosInstance
})
new Vue({
el: '#app',
router,
store,
securedAxiosInstance,
plainAxiosInstance,
render: h => h(App)
})
And in components I can successfully use them like:
this.$http.secured.get('/items')
The problem is that I am unable to use them in store where I get:
Cannot read property 'secured' of undefined"
I tried in store among others:
import { securedAxiosInstance, plainAxiosInstance } from '../axios'
const store = new Vuex.Store({
secured: securedAxiosInstance,
plain: plainAxiosInstance,
.....
What is the correct way to do it?
You can use this._vm inside the store which refers to the Vue instance of the current application.
So in your case:
this._vm.$http.secured.get('/items')
As alternative you can pass the Vue instance as payload to your mutation/action, like:
this.$store.commit('myMutation',this)

How do I navigate once I submit a form and receive a status of 200

I am confused about how to navigate away from a form route in view to another route, once my data has been submitted successfully.
I found this example.
Which seems like it should work, but it's a bit unclear on the Vue router side, can I instantiate a new Vue router in any component if I have a routes component already. Anyway, it seems to get the status but it doesn't push the route.
My Method:
methods: {
handleSubmit(event) {
const router = new VueRouter();
axios.post(API_ENDPOINT,
this.itemInit,
{ headers: {
'Content-type' : 'application/json',
}
}).then(response => {
this.results = response.data.results;
if(response.status == 200) {
router.push('/');
}
}).catch(error => {console.log(error)});
}
}
I am expecting to have it navigate to the root route when I get a status 200 from the server, which I am and everything works fine, just not getting this navigation.
Update: This worked for me.
methods: {
handleSubmit(event) {
const router = new VueRouter();
axios.post(API_ENDPOINT,
this.itemInit,
{ headers: {
'Content-type' : 'application/json',
}
}).then(response => {
this.results = response.data.results;
if(response.status == 200) {
this.$router.push('/');
}
}).catch(error => {console.log(error)});
}
}
Assuming you are building a single page app in your entry point (usually main.js)
You would do something similar to the following:
import Vue from 'vue'
import { router } from '#/plugins/vue-router' // This is where you declare your routes
and when you initiate your app you will have something like:
new Vue({
el: '#app',
router,
template: '<App/>'
})
Now in your component you would need to update your code to:
methods: {
handleSubmit(event) {
axios.post(API_ENDPOINT,
this.itemInit,
{
headers: {
'Content-type' : 'application/json',
}
}).then(response => {
this.results = response.data.results;
if(response.status == 200) {
this.$router.push('/');
}
}).catch(error => {console.log(error)});
}
}

Vue Axios local stored token is undefined

In Vue I am building a small Userprofile page. It is build on token-authentication using Axios. When mounting this page the token is undefined.
with login a token is placed in the localStorage.
The Axios Get request is build outside the Vue component
Api.js
import axios from 'axios'
export default () => {
return axios.create({
baseURL: `http://localhost:8081/`
})
}
Get request
import Api from '#/services/Api'
let config = {
headers: {
'Content-Type': 'application/json',
'Authorization': localStorage.getItem('token')
}
}
export default {
index () {
return Api().get('user/profile', config)
}
}
Vue
<script>
export default {
data: () => ({
user: {}
}),
mounted () {
this.user = UserProfileService.index
console.log(UserProfileService.config)
}
}
</script>
There are many advices and I tried them all. With tics, with commas etc. Who sees the big picture?
Use a request interceptor to set the Authorization header:
// Api.js
export default () => {
const instance = axios.create({
baseURL: `http://localhost:8081/`
})
instance.interceptors.request.use(function (config) {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
}, function (error) {
// Do something with request error
return Promise.reject(error)
})
return instance
}
I added the code from digital drifter, and solved the problem (with help) with changing the mounted function in Vue.
mounted () {
console.log('mounted')
UserProfileService.index()
.then((res) => {
this.user = res.data
})
}

Vue Router code firing before app creation finished?

Whenever I try to load / refresh my app via a deeplink the router code fires first. And fails because the authetication token has not been set yet... I assume that the beforeCreate of the app should be the first thing to be executed.
The browser console displays:
router beforeEnter
app beforeCreate
Router code:
...
const router = new VueRouter({
routes: [{
path: '/article/:articleId',
name: 'article',
component: Article,
beforeEnter (to, from, next) {
console.log('router beforeEnter')
// Load stuff from backend with axios
}
}]
}
Application startup code
...
Vue.use(VueRouter)
import router from './router'
new Vue({
el: '#app',
store: store,
router: router,
beforeCreate: function() {
console.log('app beforeCreate')
// get authentication token from localStorage and put in axios header
},
render: h => h(App),
})
What am I missing here? How can I make sure the app creation code is executed first?
I think the behaviour is intended and correct.
Before something get's rendered the router decides what to render.
But how to solve your problem?
First i have a persistent auth module like this:
export default {
name: 'auth',
namespaced: false,
state: {
token: undefined,
payload: undefined
},
mutations: {
clearAuth (state) {
state.token = undefined
state.payload = undefined
},
setToken (state, token) {
let payload
try {
payload = JSON.parse(atob(token.split('.')[1]))
} catch (e) {
payload = undefined
token = undefined
}
state.token = token
state.payload = payload
}
},
getters: {
token: state => state.token,
isAuthenticated: state => !!state.token,
hasRenewToken: state => !!state.payload && state.payload.renewable
}
}
Then i use vuex-persistedstate to initialise the vuex module.
import createPersistedState from 'vuex-persistedstate'
const store = new Vuex.Store({
modules: {
auth,
... // other modules
},
plugins: [
createPersistedState({
paths: ['auth']
})
]
})
Now whenever the store is created all auth informations are in the store.
And at the end i use a little wrapper for axios like this (request.js):
import axios from 'axios'
import store from '#/store'
const requestHandler = config => {
config.headers = {
'Authorization': store.getters.token
}
config.crossDomain = true
config.method = 'POST'
return config
}
const request = axios.create()
request.interceptors.request.use(requestHandler)
export default request
Now i do not import axios but request.js whereever i want to make a request.
I hope this approach helps you. At least it works for me
Have you tried loading it before the router? AFAIK the Vue object loads everything synchronous.
new Vue({
el: '#app',
store: store,
beforeCreate: function() {
console.log('app beforeCreate')
// set authentication token in axios header
},
router: router,
render: h => h(App),
})