VueJs - wait for OPTION response before page reload - vue.js

I'm trying to make a put request to backend when a user closes or refreshes the page. I've added the event listeners and I can run my functions when those events happen. But my problem is when those functions send a put request, they send an option request first, then send the put request. And this is a problem for me because when I check the backend logs I see that option request is received by the server (and gets 200 status code) but put request is not.
Here is my code:
<template>
<div id="app">
App
</div>
</template>
<script>
import axios from "axios"
export default {
name: "App",
mounted() {
window.addEventListener("beforeunload", this.reload)
},
methods: {
reload() {
this.sendRequest()
},
sendRequest() {
axios.put("http://xxxx:pp")
}
}
}
</script>
<style scoped>
</style>

One simple workaround is to use post instead of put and avoid the options request altogether. From MDN:
Cross-site requests are preflighted like this... if:
It uses methods other than GET or POST
If you don't want to do that, you'll need to handle the options request at the backend server by supplying CORS headers.

Related

Middleware is running even set to false

I created a folder middleware and a file called auth.js.
auth.js
export default function auth() {
console.log('auth!')
}
And in nuxt.config.js I'm calling it in router object.
router: {
middleware: ['auth']
},
And every page that I enter I see the console.log I put in Auth.js. And what I'm trying to do is to avoid the middleware to run in Login page, but even when I set it to false, it runs.
Login.vue
<template>
<div class="div">LOGIN PAGE!!!</div>
</template>
<script>
export default {
auth: false
}
</script>
Here, you auth: false is a confusion that you're making regarding nuxt-auth module.
Here, since you're not using that, you cannot bypass your middleware with auth: false, it doesn't have any effect tbh.
If you want to have a conditional middleware in your component, you can use this approach.
Otherwise, you can write something similar in a /middleware/auth.js file too.
You could even probably make a similar behavior of checking some auth key on the instance yourself (homemade solution).
For an approach on how to do that, check this article with the point 18. Component Metadata.

How to manually generate pages in Nuxt router with a 404 page fallback for .htaccess

I'm trying to create an SSG site with Nuxt.js.
When I access a route that isn't set in the generate property of nuxt.config.js,
I want to display the contents of a 404 page without changing the URL.(using htaccess)
The following is the site under construction
http://we-are-sober.d3v-svr.com/xxxx
This is working as expected.
http://we-are-sober.d3v-svr.com/user/xxxx
This does not work as expected.
The contents of page 404 are displayed for a moment, but soon after that, the process based on the dynamic route of "user/_id.vue" is executed.
The point of the problem is that the non-existent route behaves as if it exists.
Does anyone know how to solve this problem?
Here is the source code.
https://github.com/yhirochick/rewrite_test
404.vue
https://github.com/yhirochick/rewrite_test/blob/master/pages/404.vue
user/_id.vue
https://github.com/yhirochick/rewrite_test/blob/master/pages/user/_id.vue
nuxt.config.js
https://github.com/yhirochick/rewrite_test/blob/master/nuxt.config.js#L43-L45
.htaccess
https://github.com/yhirochick/rewrite_test/blob/master/static/.htaccess
I am Japanese. The above text is based on Google Translate.
It may be difficult to understand, but thank you.
My way of handling this kind of issue while minimizing the API calls required are following those steps:
generate a brand new Nuxt project
install axios: yarn add -D axios
add this to the nuxt.config.js file
import axios from 'axios'
export default {
...
generate: {
routes: async () => {
const users = await axios.get('https://jsonplaceholder.typicode.com/users')
return users.data.map((user) => ({
route: `/users/${user.id}`,
payload: user,
}))
},
fallback: 'no-user.html', // this one is not needed anymore if you ditch the redirect!
},
}
This will generate all the needed routes, while keeping the calls to a minimum thanks to payload that will be passed later on to the pages. More info can be found in the docs.
then, creating the /pages/users/_id.vue page does the trick
<template>
<div>
<div v-if="user">User name: {{ user.name }}</div>
<div v-else-if="error">{{ error }}</div>
</div>
</template>
<script>
export default {
asyncData({ payload }) {
if (payload && Object.entries(payload).length) return { user: payload }
else return { error: 'This user does not exist' } // this will also catch users going to `/users/`
},
}
</script>
create some no-user.vue page, error.vue layout and you should be gucci
At the end, we have 10 users from the mocked API. So those are the following cases:
if we go to /users/5, the user is already static so we do have it's info without any extra API call
if we go to /users/11, the user was not present at the time of build, hence he is not here and we are displaying an error
if we go to /users, we will still be sent to the /pages/users/_id page, but since the :id will be optional there, it will error and still display the error, an index.vue can of course handle this case
My github repo for this one can be found here: https://github.com/kissu/so-nuxt-generate-placeholder-users
This approach is called full static in Nuxt, as explained here: https://nuxtjs.org/announcements/going-full-static/
It's a tricky way, but I've found the code that works as I want.
https://fes.d3v-svr.com/users/xxxxxx
It's works that I expect.
User xxxxxx doesn't exist
Display 404 page
The URL /users/xxxxxx as it is
First, simply set .htaccess to rewrite non-exist page to 404 page
ErrorDocument 404 /no-user/index.html
Only above, Nuxt execute base on URL /users/xxxxxx/ and re-render the page as "UserXXXXXX" even he is not exist.
To avoid this, users/_id.vue is like bellow.
template
<template>
<div v-if="ssr">User name: {{ user.name }}</div>
</template>
script
<script>
export default {
asyncData({ payload }) {
return { user: payload, ssr:true }
},
}
</script>
It seems to be if a template is empty, nuxt will not execute the script depends on the URL.
It's very tricky, so I'll continue to how it is works.

Network Error when click <nuxt-link/> in NUXT?

Network error when click <nuxt-link/>,
this is my error details, but when i refresh the link, everything is good ? why ?
this is my entire code ,...
<template>
<div>
<nuxt-child/>
<h1>Videos</h1>
<div v-for="video in $store.state.videos" :key="video.id">
<nuxt-link :to="`/videos/${video.id}`">{{ video.customerName }}</nuxt-link>
</div>
</div>
</template>
<script>
export default {
head:{
title: 'Customer List'
},
async fetch({$axios, store}) {
let response = await $axios.get('/customers');
let videos = response.data;
store.commit('SET_VIDEOS', videos);
},
}
</script>
<style lang="scss" scoped>
</style>````
Your API request is cross-origin as localhost:3000 differs from localhost:8000
Your API needs to respond to the request on /api/customers with a header of Access-Control-Allow-Origin: *. This enables the API to be called from any origin page. Ideally in the future you would want to replace this "wildcard" * with the actual origin but for testing this is fine.
I assume your API is an Express one, in this case adding this to your application would force all requests to utilise a wildcard CORS:
// Set middlware
app.use(function (req, res, next) {
// URL of website to allow or a wildcard
res.setHeader('Access-Control-Allow-Origin', '*');
// Continue to next layer of request/middleware
next();
});
Alternatively you could also set the origin to http://localhost:8000
As a side note, in your example code I see you are using the Vuex store and have a method to make the API call before committing to the store.
If you ever plan on repeating this API call on another component, it would be advised to turn your function into an action within the Vuex store so it is in one central, reusable place.

Facebook Oauth2 cannot manually open the consent dialog Vuejs

I am trying to "Manually Build a Login Flow" according to these docs here: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/
The idea is that i want to generate an one time authorization code, then send it to my back end so it can generate there the access token and then get the user data.
The docs above nicely have sections like "Invoking the Login Dialog and Setting the Redirect URL" and "Exchanging Code for an Access Token" along with the respective endpoints to hit, which is exactly what i want. So I started implementing the dialog invocation on the front end which is a vuejs app, so i can generate the authorization code to send it to my server.
Here is the code:
<script>
import axios from "axios";
export default {
methods: {
facebookAuth(){
axios.get('https://www.facebook.com/v4.0/dialog/oauth?client_id=MY_CLIENT_ID&redirect_uri=http://localhost:3000&state="I AM A STRING"', {
headers:{
'Access-Control-Allow-Origin': '*',
}
})
.then(res=>{
console.log(res);
})
}
}
};
</script>
The first issue here is that i get CORS error, even with my anticors chrome extension open. So i pass it to this proxy https://cors-anywhere.herokuapp.com/
and I manage to make it work, but no consent dialog opens. I just get a http response with an html page code as a response body.

Why console.log() outputs in middleware are only visible on the server when entering page directly?

I tried to test if I can output something in the middleware only on certain processes. But if I use the following code - process.server seems always to work - also when I enter the route directly via browser. Other outputs are only visible when I change the route via router. I'm using Nuxt in the universal mode. What's happening there?
Actually I want to feed the store from localstorage user data and then redirect the user when this page is a guarded one. This could be only done from process.client where localStorage is defined. Can it be done with middleware at all? And also when entering the page directly?
middleware/test.vue
export default function (context) {
if (process.server) {
console.log('MIDDLEWARE SERVER')
}
if (!process.server) {
console.log('MIDDLEWARE NON-SERVER')
}
if (process.client) {
console.log('MIDDLEWARE CLIENT')
}
if (process.browser){
console.log('MIDDLEWARE BROWSER')
}
}
pages/test.vue
<template>
<h1>Some test Template</h1>
</template>
<script>
export default {
middleware: ['test']
}
</script>
After digging deep into this I found an answer from a Nuxt team member. Obviously this is the intended default behavior of middleware in the universal mode to run on page refresh only on server. The documentation wasn't that clear about it.
The only way to get stored data in the page refresh scenario is to use cookies like this.
//middleware/auth.js
export default function(context) {
context.store.dispatch("initAuth", context.req)
}
Then:
//store/index.js
actions: {
initAuth(vuexContext, req) {
if(req) {
if (!req.headers.cookie) {
return
}
// go get the cookie ;)
}
}
}