Nuxtjs Axios onRequest() not executed for asnycData request - vue.js

I have configured axios plugin onRequest helper to set Authorization header on API requests like below
1. export default function({ $axios, redirect, app, store }) {
2. $axios.onRequest(config => {
3. var requestURL = config.url;
4. console.log("Making request to " + requestURL);
5. const token = store.state.user.account.token;
6. if (token) {
7. config.headers.common["Authorization"] = `Bearer ${token}`;
8. console.log("Added authorization header");
9. }
10. });
This onRequest helper get invoked for actions in store. But for asyncData in page component, call reaches till line 2 above but never enters the onRequest function.
import axios from "axios";
asyncData({ params }) {
console.log("params: " + params);
return axios
.get(`http://localhost:8080/user/id/${params.id}`)
.then(res => {
return { userData: res.data };
})
.catch(e => {
error({ statusCode: 404, message: "User not found" });
});
}
As I understand all Axios requests should pass through onRequest helper function. Am I missing something here? How to fix this?

When you import axios from 'axios' you're not using the configuration for the axios instance that you specified initially. Instead, you're using an entirely new axios instance.
The correct way would be to leverage the $axios instance from the Nuxt context.
asyncData(context) {
await context.$axios...
}

You can also use the $axios instance directly. An example is:
asyncData({$axios}) {
await $axios...
}

Related

How to add token in nuxt axios instanse

I try to create axios instance and add token header.
const apiClient = axios.create({
baseURL: "..."
});
apiClient.interceptors.request.use(
(config) => {
const token = localStorage.getItem("auth._token.local");
if (token) {
config.headers["Authorization"] = 'Bearer ' + token;
}
return config;
},
function(error) {
return Promise.reject(error);
}
);
But it throw an error localStorage is not defined.
I think the error throw because I use it in fetch hook on page, but there is no localStorage on server-side. How should I modify my code?
If this piece of code is indeed inside fetch, as you say, you are correct. fetch is called first on the server, so there is no localStorage because you have no localStorage API without a browser.
You could use nuxt's context to check whether you are on the client or the server like:
// Client-side
if (process.client) {
// ...your code checking for localhost
} else {
// do whatever fallback on the server side....
}
more info:
https://nuxtjs.org/api/context

Axios Interceptors just working after page reload

I'm trying to send the Authorization header inside of all requests, when user is logged in my application.
but, whatever i do, it does not work.
Here is my axios instance and interceptor code.
import axios from 'axios'
import storage from '#/services/storageService'
const user = storage.getObject('currentUser')
export const http = axios.create({
baseURL: 'http://localhost/api',
})
http.interceptors.request.use((config) => {
if(user){
console.log(user)
config.headers.Authorization = user.token
}
return config
}, (err) => {
console.log(err)
return Promise.reject(err)
})
in my modules i'm importing the http instance like this
import { http } from '#/http'
export const getItems = () => {
return http.get('items').then( response => response.data)
}
So, clarifying, this code above works, but the header is not present on my request.
To get the interceptor working i need to force a page reload.
Anyone know how can i avoid this?
I solved my problem following #jacky's tip. Now my code runs as following.
import axios from 'axios'
import storage from '#/services/storageService'
export const http = axios.create({
baseURL: 'http://localhost/api',
})
http.interceptors.request.use((config) => {
let user = storage.getObject('currentUser')
if(user){
console.log(user)
config.headers.Authorization = user.token
}
return config
}, (err) => {
console.log(err)
return Promise.reject(err)
})

Axios not sending header on patch but does on get-requests

I'm making a web app that uses Axios.
I have a base service class that has an interceptor that will add the access token to each request. However, the interceptor wont add the token on my PATCH request, only on the GET request.
My base api service
import axios from 'axios'
export default class api {
constructor (path) {
this.api = axios.create({
baseURL: 'http://localhost:1337/' + path
})
this.api.interceptors.request.use(config => {
config.headers['x-access-token'] = localStorage.getItem('jwt-token')
return config
})
this.api.interceptors.response.use(undefined, (err) => {
if (err.response.status === 401) {
throw err
} else {
throw err
}
})
}
}
The service that extends the base
import Api from './api'
export default class ProfileService extends Api {
constructor () {
super('profile/')
}
me () {
return this.api.get('/me')
}
updateProfile (uuid, data) {
return this.api.patch('/' + uuid, data)
}
}
Axios does add the token to PATCH requests if I make a global interceptor like this:
axios.defaults.headers.common['x-access-token'] = localStorage.getItem('jwt-token');
I do not want to do this though, as it will send the token to other servers as well.
Any ideas on why my interceptor wont add the token when specified per instance? Is this a bug with Axios?
The OPTIONS-request has the following headers:
Access-Control-Allow-Headers:x-access-token,X-Requested-With,Content-Type,Accept,Authorization,Origin
Access-Control-Allow-Methods:GET,PUT,POST,PATCH,OPTIONS
Thanks in advance,
Axel

Automatically log out user when token is invalidated

I have a SPA that is built on vuejs. When a user is logged in via API, the token is stored in local storage.
I need a global solution which will logout and prompt the user when the token is no longer valid. At the moment, I get "invalid token" error when accessing private API endpoints.
How do I rig axios so that ALL response of invalid tokens will trigger the logout/prompt code?
Here is an simple example with axios. It use a Bearer token for authentification.
import axios from "axios";
import { useUserStore } from "#/store/userStore";
const apiClient = axios.create({
baseURL: ""http://127.0.0.1:8001",
headers: {},
});
apiClient.interceptors.response.use(
(response) => response,
async (error) => {
const config = error?.config;
if (error?.response?.status === 401) {
const result = await refreshToken();
if (result) {
config.headers = {
...config.headers,
authorization: `Bearer ${result?.token}`,
};
}
return axios(config);
}
);
const refreshToken = async () => {
/* do stuff for refresh token */
// if refresh token failed
try {
useUserStore().actionLogout();
} catch (error) {
console.log(error);
} finally {
loacalStorage.clear();
}
};
you can write a function that clears your local storage after some time and logout user

vue-resource not passing token in request headers

I'm new to Vuejs 2, currently using vue-resource to retrieve data from the server. However, I would need a token passed in the request header at the same time in order to retrieve the data from the server.
So the problem is, I am unable to retrieve data because the token is not passed into the request header, using vue-resource.
Here is the method that uses the vue-resource's interceptor (to pass in the token) to intercept the GET request:
test () {
this.$http.interceptors.push((request) => {
var accessToken = window.localStorage.getItem('access_token')
request.headers.set('x-access-token', accessToken)
return request
})
this.$http.get(staffUrl)
.then(response => {
console.log(response)
}, (response) => {
console.log(response)
})
}
Documentation for vue-resource, HTTP: https://github.com/pagekit/vue-resource/blob/develop/docs/http.md
When I try to GET the data, i end up with an error 403 (forbidden) and after checking the request headers in the dev tools, I also could not find the token in the request headers.
Please tell me where I went wrong because I'm really new to this so i appreciate any help! Thank you!
Setting interceptors inside the component using $http doesn't work, or at least it doesn't in my testing. If you examine/log this.$http.interceptors right after your push in the test method, you'll note that the interceptor was not added.
If you add the interceptor before you instantiate your Vue, however, the interceptor is added properly and the header will be added to the request.
Vue.http.interceptors.push((request, next) => {
var accessToken = "xyxyxyx"
request.headers.set('x-access-token', accessToken)
next()
})
new Vue({...})
Here is the test code I was using.
Also note, if you are using a version prior to 1.4, you should always call the next method that is passed to the interceptor. This does not appear to be necessary post version 1.4.
please go through this code
import vueResource from "vue-resource";
import { LocalStorage } from 'quasar'
export default ({
app,
router,
Vue
}) => {
Vue.use(vueResource);
const apiHost = "http://192.168.4.205:8091/";
Vue.http.options.root = apiHost;
Vue.http.headers.common["content-type"] = "application/json";
Vue.http.headers.common["Authorization"] = "Bearer " + LocalStorage.get.item("a_t");
Vue.http.interceptors.push(function(request, next) {
console.log("interceptors", request);
next(function(response) {
});
});
}