Nuxt.js router.push doesn't fully redirect to another page while using asyncData query - laravel

I am using asyncData query in one of my pages:
async asyncData({$axios, query}) {
const id = query.id;
try {
const {data} = await $axios.$get(`http://localhost:8000/api/question/${id}`);
return {
question: data
}
} catch (e) {
console.log(e);
}
},
Whenever I try to access another route from this page, for example:
#click="$router.push('/solution'); addTodo(question.keywords); addTodo(option.keywords)">
It redirects me to this page /solution, but the request to access API still goes from previous page (question/id)
Accessing localhost:3000/solution page:
CORS works in every other page, so I think the issue is here with redirections.
What would be possible solutions to fix this?
Also, this is what I see in Network tab:
I think referer should be: localhost:3000/solution

Adding 'paths' => ['api/*'] to Laravel back-end CORS config helped.

Related

How could be Laravel Socialite be integrated with a SPA?

I know we have the stateless() and and getTargetUrl() methods, than i am trying this at my controller:
public function socialRedirect($provider){
return Socialite::with($provider)->stateless()->redirect()->getTargetUrl();
}
The problem is that in my SPA front end, i can't make a sucessfull request to the provided url as like in the code below:
async facebookLogin() {
try {
const url = await this.$axios.$get('/auth/social/facebook')
this.$axios.$get(url)
} catch (error){
console.log(error)
}
},
I get CORS related stuff errors:
OPTIONShttps://www.facebook.com/v3.3/dialog/oauth?client_id=240805606930310&redirect_uri=http://localhost:8000/api/auth/social/facebook/callback&scope=email&response_type=code
CORS Missing Allow Origin
What am i doing wrong? I am specially confused since i can access the URL by copying it and pasting in another browser tab, but i can't sucessfully make the AJAX request to it.

Send POST request to Laravel web.php route

I have a simple Vue app in which I am sending POST request with options (table filtering variables) to the back-end. I want to be able to destructure the object and debug it in my TestController in Laravel 8, so I want to send the options to web.php via URL, not to api.php. Since options is an object, I cannot just drop it in the URL.
Ultimately I want to be able to preview my Laravel respond in browser, so I know it returns correct data from server.
So how can I achieve this?
in Vue FormComponent <form #submit="formSubmit"> and script
function formSubmit(e) {
e.preventDefault();
let currentObj = this;
axios.post('/formSubmit', {
name: this.name,
description: this.description
}).then(function(response) {
currentObj.output = response.data;
console.log(currentObj);
}).catch(function(error) {
currentObj.output = error;
});
}
Firstable, create POST route for your request. Then just make POST request to this route url and put your POST params (your object) to request body. You can use Axios as example
let filterOptions = {...};
axios.post(url, filterOptions).then().catch();
UPD And response for your request you can see in browser developer console on network tab

Laravel: Redirect the user to a custom 404 page when the given params are invalid

I made an application where a user can create some papers and see all data in a template. Every paper has a joincode which is generated at its creation.
I defined the join route in my web.php like this:
Route::get('/conceptPaper/lobby/{joincode}', 'App\Http\Controllers\ConceptPaperController#join');
and the join function in the controller the following way:
public function join($joincode)
{
try {
$conceptPaper = ConceptPaper::where('join_code', $joincode)->firstOrFail();
return response()->json($conceptPaper);
} catch(ModelNotFoundException $e)
{
return view('errors.404');
}
}
I used firstOrFail to check if the join code exists. If it exists it should return a response, otherwise it should redirect the user to a custom 404 page.
I created a custom component which gets the join code as a route param and shows the concept paper
{
path: '/conceptPaper/lobby/:joincode',
name: 'conceptPaper',
component: () => import('./views/ConceptPaper.vue')
},
So when the user joins a lobby with the right code he gets redirected to the page with all data from the corresponding paper:
showPaper: async function (conceptPaper) {
const joinCode = conceptPaper.join_code;
this.$router.push({ name: "conceptPaper", params: { joincode: joinCode }, });
},
My problem is that when the user types in the wrong code he still gets redirected to the view. When I check the response in the network tab its shows the 404 page.
I think I built it fundamentally wrong. Can anyone tell me how to do it the right way? When the suer types in the correct join code he should see the ConceptPaper.vue view. When the code is wrong he should be redirected to the 404 page.
From your code I'm assuming that you're using VueJs as an SPA and you're retrieving the data from your laravel backend API.
Based on that, your join function is supposed to return json data that you use in your frontend, but in case the ConceptPaper was not found, you return a view instead of json, which won't change much because you're just changing the data that your front-end receives, but the front-end component is not changed.
What I'd do is remove the try catch block, which will return a 404 response from the API, and handle the 404 case in vue, and create a NotFound view in vue.
Laravel
public function join($joincode)
{
$conceptPaper = ConceptPaper::where('join_code', $joincode)->firstOrFail();
return response()->json($conceptPaper);
}
Vue
router/index.js
const routes = [
// previous routes
{
path: '/not-found',
name: 'NotFound',
component: () => import('../views/NotFound.vue')
}
]
NotFound.vue
<template>
// page here
</template>
export {
name: 'NotFound'
}
And finally handle the not found API call, if you are using axios
axios.get('/conceptPaper/lobby/-1000')
.catch(function (error) {
if (error.response.status === 404) {
this.$router.push('NotFound');
}
});

Nuxt Apollo with dynamic headers for a session based authentication

Apollo is not storing the header from the query dynamically.
pages/index.vue
methods: {
fetchCars() {
const token = Cookies.get('XSRF-TOKEN')
console.log(token) // 🟢 Token is shown in console
this.$apollo.query({
query: gql`
query {
cars {
uuid
name
}
}
`,
headers: {
'X-XSRF-TOKEN': token, // â­• Fetch without header
},
})
},
},
Is there a way to set the header value new for every Apollo request?
I have a separate Frontend and Backend. For the Frontend I am using Nuxt.js with Apollo. I want to have a session based communication with my server. For this reason I need to send the CSRF-Token with every Request.
Now the problem: On the first load of the page there is no Cookie set on the browser. I do a GET-Request on every initialization of my Nuxt application.
plugins/csrf.js
fetch('http://127.0.0.1:8000/api/csrf-cookie', {
credentials: 'include',
})
Now I have a valid Cookie set on my side and want to communicate with the GraphQL Server but my header is not set dynamically in the query. Does anyone know how I can solve this?
My Laravel Backend is throwing now a 419 Token Mismatch Exception because I did not send a CSRF-Token with my request.
Link to the repository: https://github.com/SuddenlyRust/session-based-auth
[SOLVED] Working solution: https://github.com/SuddenlyRust/session-based-auth/commit/de8fb9c18b00e58655f154f8d0c95a677d9b685b Thanks to the help of kofh in the Nuxt Apollo discord channel 🎉
In order to accomplish this, we need to access the code that gets run every time a fetch happens. This code lives inside your Apollo client's HttpLink. While the #nuxtjs/apollo module gives us many options, we can't quite configure this at such a high level.
Step 1: Creating a client plugin
As noted in the setup section of the Apollo module's docs, we can supply a path to a plugin that will define a clientConfig:
// nuxt.config.js
{
apollo: {
clientConfigs: {
default: '~/plugins/apollo-client.js'
}
}
}
This plugin should export a function which receives the nuxt context. It should return the configuration to be passed to the vue-cli-plugin-apollo's createApolloClient utility. You don't need to worry about that file, but it is how #nuxtjs/apollo creates the client internally.
Step 2: Creating the custom httpLink
In createApolloClient's options, we see we can disable defaultHttpLink and instead supply our own link. link needs to be the output of Apollo's official createHttpLink utility, docs for which can be found here. The option we're most interested in is the fetch option which as the docs state, is
a fetch compatible API for making a request
This boils down to meaning a function that takes uri and options parameters and returns a Promise that represents the network interaction.
Step 3: Creating the custom fetch method
As stated above, we need a function that takes uri and options and returns a promise. This function will be a simple passthrough to the standard fetch method (you may need to add isomorphic-fetch to your dependencies and import it here depending on your setup).
We'll extract your cookie the same as you did in your question, and then set it as a header. The fetch function should look like this:
(uri, options) => {
const token = Cookies.get('XSRF-TOKEN')
options.headers['X-XSRF-TOKEN'] = token
return fetch(uri, options)
}
Putting it all together
Ultimately, your ~/plugins/apollo-client.js file should look something like this:
import { createHttpLink } from 'apollo-link-http'
import fetch from 'isomorphic-fetch'
export default function(context) {
return {
defaultHttpLink: false,
link: createHttpLink({
uri: '/graphql',
credentials: 'include',
fetch: (uri, options) => {
const token = Cookies.get('XSRF-TOKEN')
options.headers['X-XSRF-TOKEN'] = token
return fetch(uri, options)
}
})
}
}

Symfony2 send back login form on each AJAX request

I'm doing a back-office image upload form using Symfony 2.5.12 (yeah I know I'm a little out of date, but I will work on that soon :)). I want to upload the images via AJAX, but I get a 302 redirect to the login form on every AJAX request I send.
Here is the JS part on my stuff (it is simplified because for the moment I just want to do a successful AJAX call without 302 redirect to the login page, so I deleted the data related stuff) :
form.addEventListener('submit', event => {
event.preventDefault();
const url = form.getAttribute('action'); // '/admin/uploadImage'
fetch(url)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
});
And here is my action in my controller, bound to /admin/uploadImage URL :
public function uploadAction() {
return new JsonResponse(array('test' => 'hello world'));
}
Every /admin URL requires ROLE_ADMIN role, I defined it in security.yml :
security:
#...
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
This way, it is normal that a login form shows when I want to access to this kind of URL. But when I trigger my AJAX call, I'm already logged in because I'm on /admin/gallery page.
Does anybody can figure out what is wrong with what I'm doing ?
Thank you very much.
I absolutely don't know why, but it seems the issue was related to whatwg-fetch fetch implementation. I replaced it with axios and the problem is gone.

Resources