I use sanctum for my vue Axios operations. I deploy to my shared hosting and I get this error in the chrome console:
GET http://foo.xyz/city 401 (Unauthorized)
bootstrap.js :
window._ = require('lodash');
try {
window.Popper = require('popper.js').default;
window.$ = window.jQuery = require('jquery');
require('bootstrap');
} catch (e) {}
window.axios.defaults.withCredentials = true;
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
Axios Get :
getCity() {
axios.get('/api/city')
.then((response) => {
this.cities= response.data;
})
.catch(function (error) {
console.log(error);
});
},
Everything is working in my localhost when I deployed this project into my shared hosting nothing worked, so how I can run this in my shared hosting?
I added the following code to the .env
SANCTUM_STATEFUL_DOMAINS="foo.xyz"
and problem solved.
PS:
foo.xyz is not the actual domain, I gave a different domain for security reasons.
Related
The Sanctum Auth system on my local machine works well and I have no errors. But my deployed app is having trouble with authorizing a user. When I login it sends a request to get the user data then redirects. After auth completes you are redirected and the app make a GET request for more data. This GET route is guarded using laravel sanctum. But the backend is not registering that the user has made a successful login attempt so it sends a 401 Unauthorized error. Here is some code...
loadUser action from store.js
actions: {
async loadUser({ commit, dispatch }) {
if (isLoggedIn()) {
try {
const user = (await Axios.get('/user')).data;
commit('setUser', user);
commit('setLoggedIn', true);
} catch (error) {
dispatch('logout');
}
}
},
}
Route Guard on the routs.js checking to see isLoggedIn (which is just a boolean store locally)
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// if (to.meta.requiresAuth) {
if (isLoggedIn()) {
next();
} else {
next({
name: 'home'
});
}
} else {
next();
}
})
It was pointed out that I had forgotten the withCredetials setting for axios in bootstrap.js. I made this addition but my issue still remains.
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.axios.defaults.withCredentials = true;
Route middleware guard on the server side (this is where the request is getting turned away)
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('trucks', 'Api\TruckController');
});
In the laravel cors.php config file I changed the "supports_credentials" from false to true
'supports_credentials' => true,
It seems to me that the cookie information is not being over the api call (but I'm really not sure). This setup is working on my local machine but not on the server that I have deployed to.
Needed to add an environment variable to the .env file for SANCTUM_STATEFUL_DOMAINS and made that equal the domain name.
In the laravel sanctum.php config file...
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,127.0.0.1')),
how to properly connect third-party plug-ins when developing on laravel?
I need the fullpage.js library
downloaded it via npm
in the resources/js/bootstrap.js file I added require ('fullpage.js');
In the resources/js/app.js file I added
$ (document) .ready (function () {
$ ('. js-fullpage'). fullpage ({});
});
I launch the project and I see in the console
app.js: 4655 jQuery.Deferred exception: $ (...). fullpage is not a function TypeError: $ (...). fullpage is not a function
at HTMLDocument. <anonymous> (http: // localhost: 3000 / js / app.js: 770: 21)
at mightThrow (http: // localhost: 3000 / js / app.js: 4371: 29)
at process (http: // localhost: 3000 / js / app.js: 4439: 12) undefined
app.js: 770 Uncaught TypeError: $ (...). fullpage is not a function
as if it does not see the connection it's a library ..
and generally my call code from resources/js/app.js is why you are ABOVE than resources/js/bootstrap.js, although they are connected in a different order
my bootstrap file
try {
window.$ = window.jQuery = require('jquery');
} catch (e) {
}
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found:https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
require('fullpage.js');
Can you try to include it like
require('fullpage')
or you can try to pass full path
Add it to your webpack.mix.js and run npm run dev or npm run prod depending on your environment:
mix.js([
'resources/assets/js/app.js',
'path/to/fullpage.js',
], 'public/js/app.js')
I've got what's basically the default Vue JS scaffolding that comes with Laravel.
// app.js
require('./bootstrap');
window.Vue = require('vue');
const app = new Vue({
el: '#app',
methods: {
refreshToken: function() {
console.log('refreshing the token');
}
}
});
// bootstrap.js
window._ = require('lodash');
window.Popper = require('popper.js').default;
try {
window.$ = window.jQuery = require('jquery');
require('bootstrap');
} catch (e) {}
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
This should be familiar to anyone who has used Vue JS with Laravel before.
Now i've tried to add an axios interceptor to handle errors, i've done this below the X-Requested-With header in bootstrap.js
window.axios.interceptors.response.use(
response => response,
error => {
// Show the user a 500 error
if (status >= 500) {
console.log({500:error});
}
// Handle Session Timeouts
if (status === 401) {
console.log({401:error});
app.refreshToken();
}
// Handle Forbidden
if (status === 403) {
console.log({403:error});
}
return Promise.reject(error)
}
);
The console.log() instances work fine to verify that it is working.
However app.refreshToken() does not work (and does not give an error either?).
I'm not that surprised since I haven't imported it or anything.
But i've tried this at the top of bootstrap.js: import app from './app.js';
And npm run watch now throws a warning:
"export 'default' (imported as 'app') was not found in './app.js'
I modified app.js to change const app to be export const app but this didn't make any difference.
I'm pretty sure I am just missing some basic understanding of importing and exporting within es6 but unfortunately I can't find anything on Google that will explain it.
Most of my Googling of how to setup this axios interceptor to handle errors has come up with examples using vuex. I really don't want to bring in vuex just to resolve this as I don't want to touch it until i'm sure it's necessary for my particular app and it definitely seems overkill just to be able to follow a tutorial.
How can I call my app.refreshToken() method or access my vue instance within the axios interceptor?
After
require('./bootstrap');
window.Vue = require('vue');
const app = new Vue({
el: '#app',
methods: {
refreshToken: function() {
console.log('refreshing the token');
}
}
});
Add what the error says it's missing:
"export 'default' (imported as 'app') was not found in './app.js'
Just add this:
export default app;
That might solve the compilation problem, as for the call to the function, i have not tested it yet... came with a very similar problem 15 minutes ago..
I am trying to perform an ajax request with axios but I need it to be an https request.
axios.get('/relativeurl')
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
I can't seem to be able to find any configuration options for https. Obviously the easy way would be to use an absolute path and just set https in front of it but this is used on multiple domains.
Can anyone tell me if it is possible to default the ajax requests from axios with the https protocol?
You can do it through axios.create
var instance = axios.create({
baseURL: window.location.origin
});
instance.post() //etc
Also, u can directly modify axios global configuration. Just add your configuration right after the import axios from 'axios';
window.axios = axios; //seems like it doesn't work without making a global object
window.axios.defaults.baseURL = window.location.origin;
When I run node app.js myself, I do not get a CORS error in the browser. When I run it as a service, I do not get the error on the OPTIONS request, but I do get the error on the POST request.
I created the service using nssm. I configured the service to log in with the same account I use to run the node process.
var express = require('express');
// The `socket` module initializes socket.io for other endpoints
var io = require('./modules/socket');
var upload = require('./routes/upload');
var app = express();
app.configure(function () {
app.use(express.cookieParser());
app.use(express.session({secret: 'secret', key: 'express.sid'}));
});
app.set('port', 5000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.all('/up', function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', 'https://####.###');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
if (req.method == "OPTIONS") {
res.send(200);
} else {
next();
}
});
app.post('/up', upload.upload);
Can you think of a reason why the error on POST will only occur when it is running as a service?
Found the problem. When creating the service with NSSM, the Startup Directory needed to be the location of the app's main javascript file, not the node executable's location.
It looks like it was permissions problem when writing to disk.