axios-module
axios-module copied to clipboard
asyncData + extending axios
Hey there,
Awesome job.
I may be just an idiot but I've spent the better part of 12 hours on this now.
Code is working great when used in methods, etc. But when I use it in asyncData, console informs me that the extension is working but it isn't adding the header I set. Please note: it does add the header I set in this with methods, but not in app via asyncData.
Here's some of my code
axios.js `export default function ({ $axios, redirect }) { $axios.onRequest(config => {
$axios.setHeader('test', 'DmiGiYKxwYJ1jMfH9gtFBPgLzmwDS0HPWiM3wuugzUUqlA4Z6PbN8pnYRpEmeU4FRslHbY7M91YF1c3QGTCmo7J2oHTseE0mbe8Z')
// console.log($axios.defaults)
console.log(config)
console.log('Making request to ' + config.url + ' and adding api')
})`
asyncData in main vue page `async asyncData ({ app, params, store }) { console.log('app', app)
const events = await app.$axios.$get('/events/finder?search='+store.state.frontState.search+'&distance='+store.state.frontState.distance+'&type='+store.state.frontState.type, {
headers: {
latitude: store.state.location.lat,
longitude: store.state.location.lon
}
})
// console.log('events',events)
return { events }`
The only header not passing through is the one set through extending. It works when through method but when calling via app.$ it's not working. I can pass through the header manually in asyncData and the code works. But through the extended axios area it's not setting it, but is firing the 'Making request to' console.log
I'm having this issue as well, the axios plugin isn't setting the headers before the asyncData req is sent (perhaps a race condition?). I've noticed this only happens when I navigate to that page, when I go to the url directly the plugin works as expected.
Hey sschadwick, I got around this by changing how I set the headers beforehand:
Rather than using the out of the box .setHeader that they encourage, I simply took the config that gets passed into the plugin and manually set it like any variable. So instead of:
` export default function ({ $axios, redirect }) { $axios.onRequest(config => {
$axios.setHeader('test', 'DmiGiYKxwYJ1jMfH9gtFBPgLzmwDS0HPWiM3wuugzUUqlA4Z6PbN8pnYRpEmeU4FRslHbY7M91YF1c3QGTCmo7J2oHTseE0mbe8Z')`
I did
` export default function ({ $axios, redirect }) { $axios.onRequest(config => {
config.headers.test = 'DmiGiYKxwYJ1jMfH9gtFBPgLzmwDS0HPWiM3wuugzUUqlA4Z6PbN8pnYRpEmeU4FRslHbY7M91YF1c3QGTCmo7J2oHTseE0mbe8Z'
`
Works fine now and is stable, but is not the way the docs laid everything out. I think setHeader gets re-written by the headers in the actual call, vs my method simply adds it to the default config that gets pulled prior to call
Glad you got it to work! I noticed that my plugin was attaching the token to axios defaults AFTER the asyncData request was sent. Here's what I did to solve the issue. This way sets the token once, so you don't have to worry about race conditions for each $axios.onRequest
.
// nuxt.config.js
// mount plugin under `auth.plugins` instead of `plugins` for plugin access to $auth
auth: {plugins: [{src: '~/plugins/axios.js', ssr: true}]}
// ~/plugins/axios.js
export default ctx => {
let token = ctx.app.$auth.getToken('shibboleth');
ctx.app.$axios.setHeader('Authorization', token);
}
Hi,
Please help me,
on my ~/plugins/axios
import Cookie from 'js-cookie';
export default function ({ $axios, redirect }) {
let __token = Cookie.get("token");
$axios.defaults.headers.common.Authorize = __token;
$axios.onRequest(config => {
console.log($axios);
console.log('Making request to ' + config.url)
})
$axios.onError(error => {
const code = parseInt(error.response && error.response.status)
const data = error.response.data;
if (code === 400) {
redirect('/400')
}
})
}
the I have an action from my module ~/store/module/login/actions
....
function verifyCode ({app, commit}, data) {
let post = querystring.stringify(data);
return this.$axios.$post('/login/otp', post)
.then(
data => {
Cookie.set('token', data.data.user.token);
Cookie.set('uid', data.data.user.userid);
commit('SET_AUTH',{
token : data.data.user.token,
id : data.data.user.userid
});
// dispatch user information from profile
console.log(this.$store)
this.dispatch('profile/getUserDetails',{},{root: true});
}
);
}
....
but on execution of getUserDetails
,
It didn't get the token from the Cookie.
But on refresh it's working
Can reproduce this as well
I think the axios module doesn't respect the setting in plugins settings when called from server. I set up the axios to use https, but whenever there is an asyncData call, it goes to http instead of https. But if it is used on the client side, everything works fine.
Reproduction repo of @WangHansen https://codesandbox.io/s/m3z9y99mrj
Any update for this? I am experiencing #171 and #174 as well which should be related to this issue.
+1
I've just come across a similar issue when using Nuxt in SPA mode...
If I attempt to set the Authorization header within the onRequest
hook, the first call to my API will fail because the token wasn't sent. When making a second call to the API all is fine and the auth header is present.
export default ({ $axios, store }) => {
$axios.onRequest((config) => {
$axios.setToken(store.state.oidc.access_token, 'Bearer')
})
}
Upon finding this post I changed my plugin to set the header directly as follows and my first call to the API receives my auth token and life is good...
export default ({ $axios, store }) => {
$axios.onRequest((config) => {
config.headers.Authorization = 'Bearer ' + store.state.oidc.access_token
})
}
This is not a bug but a misuse of users.
Use $axios.setToken
or $axios.setHeader
in onRequest
is not good practice and can cause a lot of problems, because it is changing the default value of the next requests and not the current one
@pi0 should we put a notice on docs?
@ricardogobbosouza YES sure. For http module (http.nuxtjs.org) it should be documented too.
I am having quite the similar issue but in the Nuxt middleware when using the store.dispatch()
, where my Vuex actions contain this.$axios.$get()
.
middleware/auth.js:
export default async function(context) {
if (process.server) {
const { req, redirect, store } = context;
if (!req.user) {
redirect('/login');
} else {
const user = req.user;
await store.commit('auth/received_user', {
id: user.id,
email: user.email
});
store.dispatch('subscriptions/fetchUserSubscriptionStatus');
}
} else if (process.client) {
const { store, redirect } = context;
if (!store.getters['auth/isLoggedIn']) {
redirect('/login');
}
} else {
throw new Error('Failed middleware');
}
}
As you look at the above code, I can call store.commit without any problem, once I added the store.dispatch inside middleware, it didn't run the action at all. The action works fine when I place it inside mounted().
My Vuex action:
async fetchUserSubscriptionStatus({ commit, state }) {
try {
const currentPlan = await this.$axios.$get('/subscription/userPlan');
commit('setPlan', currentPlan);
} catch (err) {
// Handle error
}
},