Where to add axios interceptors code in vue js - laravel

I am using vue js as frontend with laravel. I am using laravel passport for auth, now i wants to show some error message once received 401 unauthentic error message that mostly occurs when my token expired. so to do this i am using axios interceptors my code is like
axios.interceptors.response.use(function (response) {
return response
}, function (error) {
// const { config, response: { status } } = error
const { config, response } = error
const originalRequest = config
if (response && response.status === 401) {
//notication or redirection
this.$vs.notify({
title: 'Error',
text: response.data['message'],
iconPack: 'feather',
icon: 'icon-check-circle',
color: 'danger'
})
}
return Promise.reject(error)
})
Now Question is that where i put this code in vue js so that it call after every request & so an error message shown & redirect to login once get 401 unauthorized..
Any Suggestion from anyone.
Thanks in advance!!

app.js or add them to separate file and include in app.js. There is post about this https://medium.com/#yaob/how-to-globally-use-axios-instance-and-interceptors-e28f351bb794

Related

405 (Method Not Allowed) - Laravel and Vue.Js

Good afternoon everyone, I'm trying to implement a notification system with the possibility to mark this notification with a like.
I am using laravel 7 for the back end and vuejs for the front end.
The code works correctly on localhost, but when I deploy to Heroku it stops working and to give me the message below.
http://springalert.herokuapp.com/api/like 405 (Method Not Allowed)
Uncaught (in promise) Error: Request failed with status code 405
at createError (app.js:5347)
at settle (app.js:5608)
at XMLHttpRequest.handleLoad (app.js:4816)
Someone with any tips for the subject, I researched about it and I know that we have to configure CORS but for this version of laravel it supposedly would no longer be necessary.
follow the code, thank you for your help.
ROUTE
Route::post('/api/like/', 'NotificationController#api_like');
CONTROLLER
public function api_like(Request $request) {
$like = new Like;
$like->notification_id = $request->id;
$like->user_id = auth()->id();
$like->save();
}
VUEJS
<b-card-text class="text-right" v-if="Object.keys(notification.like).length == 0">
<a #click="makelike('success', 'Informação', notification.id)" class="a"><i class="fas fa thumbs-up"></i></a>
</b-card-text>
makelike(variant = null, title, notification_id) {
this.id = notification_id
axios.post('api/like/',{ id:this.id })
.then((response) => {
this.set_notifications()
this.$bvToast.toast('Obrigado pela tua visualização', {
title: title,
variant: variant,
solid: true
})
})
},
As user Mihai pointed out, you need to chain your POST request after a get request to csrf.
Here's how it looks like with Laravel Sanctum:
import axios from 'axios'
const baseUrl = 'http://yourdomain.com'
const api = axios.create({
baseURL: baseUrl,
withCredentials: true
})
const payload = {}
api().get('/sanctum/csrf-cookie').then(() => {
return api().post('api/like', payload).then(resp => {
// Do stuff with resp
})
})

Vuejs Laravel Passport - what should I do if access token is expired?

I am using Vuejs SPA with Laravel API as backend. I successfully got the personal access token and store in localStorage and Vuex state like below.
token: localStorage.getItem('token') || '',
expiresAt: localStorage.getItem('expiresAt') || '',
I use the access token every time I send axios request to laravel api. Every thing works well. However, initially the token was set to 1 year expiration so when I develop I didn't care about token being expired and today suddenly I thought what is going to happen if token expired. So I set token expiry to 10 seconds in laravel AuthServiceProvier.php.
Passport::personalAccessTokensExpireIn(Carbon::now()->addSecond(10));
and then I logged in and after 10 seconds, every requests stopped working because the token was expired and got 401 unauthorised error.
In this case, how can I know if the token is expired? I would like to redirect the user to login page if token is expired when the user is using the website.
Be as user friendly as possible. Rather than waiting until the token expires, receiving a 401 error response, and then redirecting, set up a token verification check on the mounted hook of your main SPA instance and have it make a ajax call to e.g. /validatePersonalToken on the server, then do something like this in your routes or controller.
Route::get('/validatePersonalToken', function () {
return ['message' => 'is valid'];
})->middleware('auth:api');
This should return "error": "Unauthenticated" if the token is not valid. This way the user will be directed to authenticate before continuing to use the app and submitting data and then potentially losing work (like submitting a form) which is not very user friendly.
You could potentially do this on a component by component basis rather than the main instance by using a Vue Mixin. This would work better for very short lived tokens that might expire while the app is being used. Put the check in the mounted() hook of the mixin and then use that mixin in any component that makes api calls so that the check is run when that component is mounted. https://v2.vuejs.org/v2/guide/mixins.html
This is what I do. Axios will throw error if the response code is 4xx or 5xx, and then I add an if to check if response status is 401, then redirect to login page.
export default {
methods: {
loadData () {
axios
.request({
method: 'get',
url: 'https://mysite/api/route',
})
.then(response => {
// assign response.data to a variable
})
.catch(error => {
if (error.response.status === 401) {
this.$router.replace({name: 'login'})
}
})
}
}
}
But if you do it like this, you have to copy paste the catch on all axios call inside your programs.
The way I did it is to put the code above to a javascript files api.js, import the class to main.js, and assign it to Vue.prototype.$api
import api from './api'
Object.defineProperty(Vue.prototype, '$api', { value: api })
So that in my component, I just call the axios like this.
this.$api.GET(url, params)
.then(response => {
// do something
})
The error is handled on api.js.
This is my full api.js
import Vue from 'vue'
import axios from 'axios'
import router from '#/router'
let config = {
baseURL : process.env.VUE_APP_BASE_API,
timeout : 30000,
headers : {
Accept : 'application/json',
'Content-Type' : 'application/json',
},
}
const GET = (url, params) => REQUEST({ method: 'get', url, params })
const POST = (url, data) => REQUEST({ method: 'post', url, data })
const PUT = (url, data) => REQUEST({ method: 'put', url, data })
const PATCH = (url, data) => REQUEST({ method: 'patch', url, data })
const DELETE = url => REQUEST({ method: 'delete', url })
const REQUEST = conf => {
conf = { ...conf, ...config }
conf = setAccessTokenHeader(conf)
return new Promise((resolve, reject) => {
axios
.request(conf)
.then(response => {
resolve(response.data)
})
.catch(error => {
outputError(error)
reject(error)
})
})
}
function setAccessTokenHeader (config) {
const access_token = Vue.cookie.get('access_token')
if (access_token) {
config.headers.Authorization = 'Bearer ' + access_token
}
return config
}
/* https://github.com/axios/axios#handling-errors */
function outputError (error) {
if (error.response) {
/**
* The request was made and the server responded with a
* status code that falls out of the range of 2xx
*/
if (error.response.status === 401) {
router.replace({ name: 'login' })
return
}
else {
/* other response status such as 403, 404, 422, etc */
}
}
else if (error.request) {
/**
* The request was made but no response was received
* `error.request` is an instance of XMLHttpRequest in the browser
* and an instance of http.ClientRequest in node.js
*/
}
else {
/* Something happened in setting up the request that triggered an Error */
}
}
export default {
GET,
POST,
DELETE,
PUT,
PATCH,
REQUEST,
}
You could use an interceptor with axios. Catch the 401s and clear the local storage when you do then redirect user to appropriate page.

No response data from Laravel API using Axios

I am setting up authentication using Laravel (Laravel Framework version 5.8.4) as a REST API, but when I make a post request using Axios, I get back an empty string.
Here is my code in Laravel: "login" endpoint in my main controller:
class MainController extends Controller
{
public function login(Request $request){
$data = [
'message' => 'yo'
];
return Response::json($data, 200);
}
}
Here is my Axios code (from Vue.js method):
methods: {
submitRegistration: function() {
axios.post('http://envelope-api.test/api/auth/login', {
name: this.form.name,
email: this.form.email,
password: this.form.password,
password_confirmation: this.form.password_confirmation
})
.then(function (response) {
console.log("here's the response")
console.log(response);
})
.catch(function (error) {
console.log(error);
});
},
}
Here is the response from Postman (it works!)
{
"message": "yo"
}
Here is the response from my axios request in console (empty string, where's the data?) :
{data: "", status: 200, statusText: "OK", headers: {…}, config: {…}, …}
To get data from axios you should use response.data, not just response.
Edit: Try to respond with the helper.
response()->json($data);
I've got this figured out. Thanks for your help.
I had this chrome extension installed to allow CORS (Cross Origin Resource Sharing) so I could do API requests from localhost (apparently, not needed for Postman?).
I turned it off and installed it locally on Laravel using this post (answer from naabster)
After I installed this way, it worked regularly.

Laravel and vue.js, failed to call api in vue.js and laravel project

im tring to get user data from my laravel with vue js, however i trying its always fail
here my laravel code in api.php route folder:
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
and here is my vue js code :
export default {
props: ['product', 'authenticatedUser'],
methods: {
getUser () {
this.$http.get('api/user/')
.then(response => {
console.log(response)
})
}
}
}
my code work for another case, but if i trying to get user data by click a button its fails, here is my error
Failed to load http://localhost/hadirr/laracore/public/api/products/:
Response for preflight is invalid (redirect)
feed#:1 Uncaught (in promise) Response {url:
"http://localhost/hadirr/laracore/public/api/products/", ok: false, status:
0, statusText: "", headers: Headers, …}
here is my complete error message :

Can't access laravel response from ajax library

// Edit: Hm...this is an firebug bug in firefox. On chrome it works...
I'm using Laravel 5.3 with Vue 2.0 and the axios ajax library.
Here is a test controller, where i return a response from laravel:
public function testMethod() {
return response('this is an error', 500);
}
Here is my ajax call:
http(`fetch-data`).then(response => {
const data = response.data;
console.log(data);
}).catch(error => {
console.log(error); // <- This doens't work, he show my nothing
alert(error);
});
The problem is, i need the error message which is returned from laravel into my client catch. But if i console.log them, he show me nothing. If i alert the error, he gives me the following message: Error: Request failed with status code 500.
Why can't i access something like error.statusCode, error.statusMessage?
Try
return response()->json('this is an error', 500);

Resources