Vue call API key on header - api

My API KEY = 2356yhtujkiw
I am using AXIOS on VUEJS as for get/post request.
API document says to add that API key as on header of all requests.
I tried setting it as axios.defaults.headers.common['header'] = '2356yhtujkiw'; but it did not work.
What's the proper way to define API KEY on header ?

it can get confusing when you're starting out, and certain terms, like header could mean different things depending on context.
There are several ways you can achieve axios calls in vue.
There's the "easy" one, where you add stuff right into a component
you can integrate it into vuex
create a custom helper/wrapper function (to use in a component or vuex)
use a the vue axios plugin
On top of that there's more than one ways to implement axios
reuse global instance
create new instance for every call
without seeing your code it's hard to know which way you're using it, but I'm going to try to give steps for a way that should make it easy enough to replicate
create a api.js in your src folder with:
import axios from 'axios'
let TOKEN = null;
export default {
setHeader(val){
TOKEN = val;
},
fetchUsers: () => {
const instance = axios.create({
baseURL: 'https://api.example.com',
headers: {
header: TOKEN
}
});
// or: instance.defaults.headers.common['header'] = TOKEN;
return instance.get('/users')
.then((result) => {
this.users = result.data
})
}
}
In a component, or Vuex, you can then...
import api from '../api.js'
// set header
api.setHeader('abc123')
// make api call
api.fetchUsers().then(r=> {console.log(r)});
This (though untested code) should work...
It's not the cleanest way of using it, but should be easy to implement in existing code.
TL;DR;
The reason axios.defaults.headers.common['header'] = '2356yhtujkiw'; doesn't work is likely because you've already created the instance, and are re-using it. Updating the default would only apply for subsequent instances created. The example above gets around that, by not using any defaults, and just inserting the headers in every new instance, which is created for every new call.

Related

Update all clients after a change in vuex state

I am using vue2 syntax and vuex , versions : vue/cli 4.5.13 and vue#2.6.14 and vuex 3.6.2
I have a simple to do project , for adding todos in a list, based on the 2019 vue tutorial by traversy.
I have a simple form ij my component to add a to do
<form #submit.prevent="onSubmit" >
and in my vuex store I have
const state = {
todos:''
};
const getters = {
allTodos: (state) => {return state.todos}
};
const actions = {
async addTodo({commit}, title){
const res = await axios.post('https://jsonplaceholder.typicode.com/todos', {
title,
completed:false
});
commit('newTodo', res.data);
}
};
const mutations = {
newTodo:(state, todo)=>(
state.todos.unshift(todo)
)
};
Is there a way to update all clients that view the todos, without clients have to refresh nothing, as soon as a new todo is added in the state, using only vuex/vue?
Thank you
Is there a way to update all clients that view the todos, without clients have to refresh nothing, as soon as a new todo is added in the state, using only vuex/vue?
No, it is not possible.
There is no link between all your clients. All your Vue/VueX code lives in a single client. Here's what you need to do to get where you want to go, and its a long way from here:
Build a backend server. Here's a Node.js guide
Build an APi in your server. Your clients will make requests to this server to get all todos, and post new todos to the server. Here's an express.js guide
You need a database to store your todos in the server. You can use something like MongoDB or an ORM like Sequelize for node.js.
Now you can either write a code to periodically request the server for todos in the background and update it in your vue components, or you can use a pub/sub library like pusher. Pusher uses WebSockets under the hood for maintaining a persistent bidirectional connection. If you want to, you can implement this on your own, you can read about it here, thanks to #Aurora for the link to the tutorial.
Here's a consolidated guide for doing all this:
https://pusher.com/tutorials/realtime-app-vuejs/
Is there a way to update all clients that view the todos, without clients have to refresh nothing, as soon as a new todo is added in the state, using only vuex/vue?
There's a couple of errors in your code:
change todos:'' to todos:[]
change state.todos.unshift(todo) to state.todos.push(todo)
This way, every time that you call addTodo action, all components connected to allTodos getter will show the latest todos
NOTE:
Vuex/Vue are reactive. So in every page that you see using that showcomponent will show you the last update. If you want to show in every USER CONNECTED, of course you don't need http request, you need WEBSOCKETS

Forward basiauth to axios

I have a site which makes an Axios request. Both the backend and vuejs frontend are on the same domain, and have the same basic auth covering them.
The issue is that whilst the pages load, as soon as an Axios request is made, it asks me again for the basic auth, which doesn't even work if I fill in the details.
Now I imagine I need to pass through the basic auth details somehow, but none of the things I have tried work (and example being below).
If anyone has any tips on passing through the auth token from the parent page to the axios request, that would be great.
const requestOne = axios.get(requestUrl)
const requestTwo = axios.get(requestUrl)
axios
.all([requestOne, requestTwo])
.then(
axios.spread((...responses) => {
<some code here>
})
)
I just answered a similar question with the 3 ways to pass around data in Vue.
You might find it helpful: How to pass v-for index to other components
However, in my opinion, the best approach would be to create a Vue plugin with your Axios client and an init method.
Consider this following (untested) example:
axiosClient.js
import Vue from 'vue';
let instance;
export const getInstance = () => instance;
export const useAxios = () => {
if (instance) return instance;
instance = new Vue({
data() {
return {
client: null,
}
}
});
methods: {
init(authToken) {
this.client = axios.create({
headers: {'Authorization': authToken }
});
}
}
}
export const axiosPlugin = {
install(Vue) {
Vue.prototype.$axios = useAxios();
},
};
Vue.use(axiosPlugin);
Once installed, you can access this in your components using $axios.init(...) and $axios.client.
You can even write API methods directly onto the plugin as well and interact with Vuex through the plugin!
You may need to tweak the plugin a little (and keep in mind this is Vue2 syntax) as I wrote this directly into StackOverflow.
You can also pass any other default values or configuration options through to the axios client by providing options to the plugin and accessing them within init.
You can learn more about plugins here: https://v2.vuejs.org/v2/guide/plugins.html

Fetching global api data in nuxt

I'm starting Nuxt project and I have to fetch basic data from my backend.
for example language dictionary or some data for leftbar and etc.
in Vue I can just call everything I need in App.vue and save it in vuex and then use whenever I want, but with Nuxt every page is different and I'm curious where should i call this global data api calls.
I'm guessing I have to create middleware and call actions if data is not loaded already or there is better solution?
You mention it's global data and you're using universal mode- I think you're looking for nuxtServerInit(). This store action runs once on the server, before created, mounted hooks etc. You can use it to populate your store with data that your components (including pages) rely on.
Take a look at the docs.
actions: {
nuxtServerInit ({ commit }, { req }) {
if (req.session.user) {
commit('user', req.session.user)
}
}
}

Axios config default GET param

I'm using Axios in my VueJS application and I want to add a default GET param in my request. I send my API-KEY through the URL ?api-key=secret and I don't want to specify this parameter each time.
I see in the documentation that we can set Global custom defaults. With that we don't have to specify the header each time. But can we do the same for get param ?
I struggled to get this to work with axios instances using the two most commonly suggested methods:
// method 1: setting axios.defaults.params at the class level
axios.defaults.params = {}
axios.defaults.params['api-key'] = secret
and
// method 2: setting the `params` attribute at an instance level
const axClient = axios.create({
baseURL: process.env.VUE_APP_BASE_URL,
params: {
api-key: process.env.VUE_APP_API_KEY
}
});
I did however, manage to get it working nicely using interceptors like this:
// create an instance with default properties
const axClient = axios.create({
baseURL: process.env.VUE_APP_BASE_URL,
});
axClient.interceptors.request.use((config) => {
// use config.params if it has been set
config.params = config.params || {};
// add any client instance specific params to config
config.params['api-key'] = process.env.VUE_APP_API_KEY;
return config;
});
The benefit of this approach is that the instance level params can be dynamic/computed per request if needed.
As a (slightly contrived) example, if you needed to add a JWT to each request (including any logic to fetch it from your storage method of choice) and even react to the logic around that. So in this toy example, if the user doesn't have a JWT in storage, redirect them to the login page instead of making the request.
Here it is:
axios.defaults.params = {}
axios.defaults.params['api-key'] = secret
If you need to call a function before each axios request, you should use an interceptor.

Reset token in vue resource - Vue2

In the main.js file i have set the vue resource to use auth headers with every requests:
Vue.use( VueResource )
let auth = validToken()
if( auth ) {
Vue.http.interceptors.push( ( request, next ) => {
request.headers.set( 'Authorization', auth.token )
request.headers.set( 'Accept', 'application/json' )
next()
} )
}
And in the logout, i am trying to delete the header this way,
resetVueRsr: () => {
this.$http.headers.common['Authorization'] = null
}
And when a user log in, then resetting the new token to the global Vue resource like this,
this.$http.headers.common['Authorization'] = res.body.token
But once a new user is logging in the site, the vue resource still sending previous token with each request. What i am missing here?
I checked the source, and it looks like all defined interceptors are added in some internal array, and then used for requests.
According to your code sample, you obtain an object with initial token somehow and then pass it inside your arrow function, so JS creates a closure for this to make this object available inside the function, and I think a lifetime of this closure is equal to a lifetime of your app. I assume that you have a sort of SPA.
Also from the source it looks like interceptors are not related to common headers, so your way of deleting and resetting won't change your interceptor.