I have used breeze-next as a boilerplate.
User register and login work perfectly but when I create a custom hook to interact with the server, Axios sends requests to front-end address, instead of the server.
I have declared the server address in .env file:
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000
Axios configuration:
import Axios from 'axios'
const axios = Axios.create({
baseURL: process.env.NEXT_PUBLIC_BACKEND_URL,
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
withCredentials: true,
})
export default axios
My custom hook:
export const useAccount = () => {
const csrf = () => axios.get('/sanctum/csrf-cookie')
const {data: user, error, mutate} = useSWR('/api/user', () =>
axios
.get('/api/user')
.then(res => res.data)
.catch(error => {
if (error.response.status !== 409) throw error
router.push('/verify-email')
}),
)
const start = async ({setErrors, setStatus, ...props}) => {
await csrf() // <-- Fails Here
axios.post('/user/account/start', props)
.then(() => mutate())
.catch(error => {
setErrors(Object.values(error.response.data.errors).flat())
})
}
return {
start
}
}
When axios sends a get request it sends the request to http://localhost:3000/sanctum/csrf-cookie which is the front-end address.
The problem was with wrong import.
I didn't pay attention to what file is IDE importing as axios into account Hook.
It was like this:
import axios from "axios"
So I changed it to:
import axios from "#/lib/axios"
Related
So basicaly I want to fetch the data from Laravel server to next js api server and this seems to be working fine for the other atributes like title but the image is not fetching and return error 500 and 'ECONNREFUSED'
Here is the code for courses inside the api colder pages/api/courses.ts
import { NextApiRequest, NextApiResponse } from "next";
import axios from "axios";
import Course from "../../models/course";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const courses = await Course.fetchAll();
res.status(200).json(courses);
}
Code for the api route on laravel
Route::get('/courses', function () {
$courses = Courses::all();
// allow to remote access
header('Access-Control-Allow-Origin: *');
return response()->json(['courses' => $courses], 200);
});
Code for the API call
const fetchCourses = async () => {
const courses = await axios.get("http://localhost:3000/api/courses", {
headers: {
"Content-Type": "application/json",
// allow cors
"Access-Control-Allow-Origin": "*",
},
});
setCourses(courses.data);
};
The image appears like that
The error that appears on image url
I fixed it by replacing the NextImage tag with normal image tag and it worked
I am using laravel passport for authentication in my laravel and vue.js ecommerce project.
After successful login, I want to redirect user to his/her dashboard.
Here is the vue dashboard page:
<template>
<div class="content-center">
<h1>Dashboard my account</h1>
<p>
{{userData.name}}
</p>
</div>
</template>
<script>
import Axios from "axios";
export default {
data() {
return {
userData: "",
authToken: ""
}
},
async beforeMount() {
let res = await Axios.get("http://localhost:8000/api/user-details", {
headers: {
Authorization: "Bearer " + this.authToken,
Accept: 'application/json'
},
});
this.userData = res.data;
// let token = await Axios.get("http://localhost:8000/api/user-login")
// this.authToken = res.data.data.auth_token
//let res = await Axios.get("http://localhost:8000/api/user-details");
},
};
</script>
Everytime I login to different user accounts, I have to set the value of authToken manually copy and pasting from Postman. I want to set this token automatically when a user logs in. How can I do this ?
Here is my api controller:
class AuthApiController extends Controller
{
public function userDetails(){
return auth()->user();
}
public function login(Request $request){
$user = User::where('email',$request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
return response()->json([
'success'=>false,
'data'=>[],
'message'=>'Login failed',
'errors'=>[]
]);
}else{
return response()->json([
'success'=>true,
'data'=>['user'=> $user, 'auth_token' => $user->createToken('AuthToken')->accessToken],
'message'=>'Login success',
'errors'=>[]
]);
}
}
Updates:
dashboard.vue
<template>
<div class="content-center">
<h1>Dashboard my account</h1>
<p>
{{userData.name}}
</p>
</div>
</template>
<script>
import Axios from "axios";
export default {
data() {
return {
userData: "",
authToken: ""
}
},
async beforeMount() {
let res = await Axios.get("http://localhost:8000/api/user-details", {
headers: {
Authorization: "Bearer " + this.authToken,
Accept: 'application/json'
},
});
this.userData = res.data;
let token = await $api.get("http://localhost:8000/api/user-login")
this.authToken = res.data.data.auth_token
},
};
</script>
Picture:
enter image description here
What should I write to import api.js ?
import $api from ./../api.js or anything else ?
Well, you can store your token in LocalStorage. And whenever you request just get it from the local storage and pass it to the request header.
If you are using Axios then you can use interceptors and just intercept your every request and pass token in the header.
Step 1.
Create a file called api.js or you can call it whatever you want.
Step 2.
Create an Axios instance in the api.js file.
import axios from 'axios';
// Put your backend url here
export const API_URL = `http://localhost:5000/api`
const $api = axios.create({
withCredentials: true,
baseURL: API_URL
})
$api.interceptors.request.use((config) => {
config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`
return config;
})
export default $api;
Step 3: Where ever you are using Axios use this exported instance so in your component you would do like this:
const userdata = await $api.get("http://localhost:8000/api/user-details");
Here you can see, we are using the $api Axios instance which we created in the api.js file instead of Axios direct.
Add also don't forget to store your token in your local storage when you getting that.
localStorage.setItem('token', "Your token goes here...");
I hope this will give you an idea.
This way, Token will be sent with every request automatically, if it exists in the localStorage.
UPDATE:
<template>
<div class="content-center">
<h1>Dashboard my account</h1>
<p>
{{userData.name}}
</p>
</div>
</template>
<script>
// import Axios from "axios";
import $api from 'put relative path of your api.js file'
export default {
data() {
return {
userData: "",
authToken: ""
}
},
async beforeMount() {
let res = await $api.get("/user-details");
this.userData = res.data;
let res = await $api.get("/user-login")
localStorage.setItem('token', res.data.data.auth_token);
},
};
</script>
I'm creating a Laravel/Vue3 app and wanted to completely separate the Laravel router from the SPA router.
In order to achieve this I created a dashboard.blade.php file which contains the following content:
<x-app-layout>
<div id="app"></div>
</x-app-layout>
Vue then simply mounts on top of that div and the app is started.
My webpack.mix.js:
const mix = require("laravel-mix");
mix.ts("resources/js/app.ts", "public/js")
.vue({ version: 3 })
.postCss("resources/css/app.css", "public/css", [
require("postcss-import"),
require("tailwindcss"),
require("autoprefixer"),
]);
The app.ts file is also quite simple:
import { createApp } from 'vue';
import App from './App';
createApp(App).mount('#app');
Which is great, but my holdup is that for subsequent requests (via Axios), I will need the user token. How can I get this token/logged in user info to my Vue3 app?
I'm using Laravel Breeze for authentication (if that helps).
Thank you,
It turns out the answer was 'extremely' simple. I had to do nothing besides removing the comment tags on this line:
And add headers as follows in your axios config:
import axios from "axios";
import store from "../store";
const Axios = axios.create({
baseURL: process.env.APP_URL,
headers: { Accept: "application/json" },
});
Axios.interceptors.request.use(
(config) => {
store.commit("setLoader", true);
return config;
},
(error) => Promise.reject(error)
);
Axios.interceptors.response.use(
(response) => {
store.commit("setLoader", false);
return response;
},
(error) => Promise.reject(error)
);
export default Axios;
Subsequent axios calls have the token attached automatically.
You can find all the required information here. Love Laravel...
I'm trying to use useEffect in my React app but also refactor things more modularly. Shown below is the heart of actual working code. It resides in a Context Provider file and does the following:
1. Calls AWS Amplify to get the latest Auth Access Token.
2. Uses this token, in the form of an Authorization header, when an Axios GET call is made to an API Endpoint.
This works fine but I thought it would make more sense to move Step #1 into its own useEffect construct above. Furthermore, in doing so, I could then also store the header object as its own Context property, which the GET call could then reference.
Unfortunately, I can now see from console log statements that when the GET call starts, the Auth Access Token has not yet been retrieved. So the refactoring attempt fails.
useEffect(() => {
const fetchData = async () => {
const config = {
headers: { "Authorization":
await Auth.currentSession()
.then(data => {
return data.getAccessToken().getJwtToken();
})
.catch(error => {
alert('Error getting authorization token: '.concat(error))
})
}};
await axios.get('http://127.0.0.1:5000/some_path', config)
.then(response => {
// Process the retrieved data and populate in a Context property
})
.catch(error => {
alert('Error getting data from endpoint: '.concat(error));
});
};
fetchData();
}, [myContextObject.some_data]);
Is there a way of refactoring my code into two useEffect instances such that the first one will complete before the second one starts?
You could hold the config object in a state. This way you can separate both fetch calls and trigger the second one once the first one finished:
const MyComponent = props => {
const myContextObject = useContext(myContext);
const [config, setConfig] = useState(null);
useEffect(() => {
const fetchData = async () => {
const config = {
headers: {
Authorization: await Auth.currentSession()
.then(data => {
return data.getAccessToken().getJwtToken();
})
.catch(error => {
alert("Error getting authorization token: ".concat(error));
})
}
};
setConfig(config);
};
fetchData();
}, [myContextObject.some_data]);
useEffect(() => {
if (!config) {
return;
}
const fetchData = async () => {
await axios
.get("http://127.0.0.1:5000/some_path", config)
.then(response => {
// Process the retrieved data and populate in a Context property
})
.catch(error => {
alert("Error getting data from endpoint: ".concat(error));
});
};
fetchData();
// This should work for the first call (not tested) as it goes from null to object.
// If you need subsequent changes then youll have to track some property
// of the object or similar
}, [config]);
return null;
};
I'm new to Redux and Redux-Observable. I'm having success in getting information from a rest API with GET and GET(ID), but I cannot get the Delete and Post to work. Sample code below that is issuing a GET request:
[EPIC File]
import { debounceTime, Observable } from 'rxjs';
import { ajax } from 'rxjs/observable/dom/ajax';
import ActionTypes from '../actions/ActionTypes';
import { receiveFeedBack, receiveDeleteFeedBackId,
receiveFeedBackId } from '../actions/FeedBackActions';
export const fetchFeedBack = (action$) => ... Working
export const fetchFeedBackId = (action$) => ... Working
//Not Working
export const deleteFeedBackById = (action$) =>
action$.ofType(ActionTypes.DELETE_FEEDBACK_REQUEST)
.debounceTime(500)
.switchMap(action =>
ajax.delete(`${ActionTypes
.FEEDBACK__URL}/posts/${action.payload.feedbackId}?key=${ActionTypes
.FEEDBACK__API_KEY}`)
.map(receiveDeleteFeedBackId.bind(action))
.takeUntil(action$.ofType(ActionTypes.DELETE_FEEDBACK_CANCELED))
.catch(error => Observable.of({
type: ActionTypes.DELETE_FEEDBACK_ERROR,
payload: error
}))
);
What am I doing wrong?