I tried these code to post data using Axios Api in Vue in I am getting these error:
Access to XMLHttpRequest at
'https://jsonplaceholder.typicode.com/todos' from origin 'null' has
been blocked by CORS policy: No 'Access-Control-Allow-Origin' header
is present on the requested resource. 16_Axios_API_CRUD.html:96 Error:
Network Error
at e.exports (spread.js:25)
at XMLHttpRequest.l.onerror (spread.js:25)
new Vue({
el: "#app",
data() {
return {
todos: [],
newTodo: "",
loading: true,
errored: false
};
},
methods: {
addToDo() {
debugger;
const _todo = {
title: this.newTodo,
completed: false
};
//const { title } = this.newTodo;
axios
.post("https://jsonplaceholder.typicode.com/todos", _todo)
.then(res => (this.todos = [...this.todos, res.data]))
}
},
mounted() {
axios
.get("https://jsonplaceholder.typicode.com/todos?_limit=5")
.then(response => (this.todos = response.data))
}
});
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<div id="app">
<input
v-model.trim="newTodo"
/>
<input
value="Add"
type="button"
v-on:click="addToDo"
/>
<section v-else>
<div v-bind:key="todo.id" v-for="todo in todos">
<div class="todo-item" v-bind:class="{'is-complete':todo.completed}">
<p>
{{todo.title}}
</p>
</div>
</div>
</section>
</div>
Anyone face this error message before? Do I need destructor which I notice in some tutorial before posting it? Not quite sure why some tutorial have destructor though.
Edit: It looks like 'slow processing' issue. I can the posted data after a long time. How do I add some 'animation' to show that it is actually in progress posting the data and in progress of returning it back?
You are using absolute URL's. There are two ways you can handle this.
Configure your server to handle CORS Headers
Configure a local reverse-proxy using a tool like webpack-dev-server or nginx.
If you choose the second, which is recommended over the other, your code will be like this:
axios
.post("/api/todos", _todo)
.then(res => (this.todos = [...this.todos, res.data]))
And in your reverse-proxy, made possible by webpack-dev-server:
module.exports = {
//...
devServer: {
proxy: {
'/api': 'https://jsonplaceholder.typicode.com'
},
secure: true
}
};
More on this:
https://www.freecodecamp.org/news/never-use-an-absolute-path-for-your-apis-again-9ee9199563be/
https://webpack.js.org/configuration/dev-server/#devserverproxy
Related
Building out an ecommerce store. Started with the products, which require no auth to pull, but do require auth to edit. This is working fine, and I suspect it's because this is happening on the client which sends auth info with all requests direct from client (ie methods hook).
However, order data does require auth to access any of it. I'm unable to access this route to generate the page using asyncData. I suspect this is because it's happening on the Nuxt server instead of on the client.
async asyncData({ $config: { apiURL } }) {
let orders = await axios.get(
`${apiURL}/orders`
);
return { orders: orders.data.data };
},
What is the correct way to do this? Set an empty data point then use mounted or created to pull and set?
Update: I got it working with as a method, but then you have to press the button to pull all the orders, that's pretty bad ux lol what do
An alternative solution would be
<template>
<section>
<div v-for="user in users" :key="user.id">
{{ user.name }}
</div>
</section>
</template>
<script>
export default {
async asyncData({ $axios, $config: { jsonPlaceholder } }) {
const fetchedUsers = await $axios.$get(`${jsonPlaceholder}/users`)
return { users: fetchedUsers }
},
data() {
return {
users: [],
}
},
}
</script>
This is using JSONplaceholder as an example, in your case you may add an additional data as you did initially.
This solution has the benefit of blocking the render of the page until the call is done (mounted() cannot).
Got it working, this is what I did:
data: () => ({
orders: []
}),
mounted() {
this.$axios.$get(`${this.$config.apiURL}/orders`).then( res => {
this.orders = res.data
})
},
Let me know if there's a better way to go
So I am writing a frontend project in VueJS. I already have a custom express backend serving an API. It's not necessarily an issue, but when I use axios, the cookies are being passed with ever request; even if I set 'withCredentials: false' and by default.
<template>
<div>
<h1>Login Vue</h1>
<input
type="text"
name="username"
v-model="input.username"
placeholder="Username"
/>
<input
type="password"
name="password"
v-model="input.password"
placeholder="Password"
/>
<button type="button" v-on:click="login()">Login</button>
<button type="button" v-on:click="getMe()">GetMe</button>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'HelloWorld',
props: {
msg: String,
},
data: function() {
return {
input: {
username: '',
password: '',
},
};
},
methods: {
login: async function() {
const user = await axios.post(
`/api/v1/users/login`,
{
username: this.input.username,
password: this.input.password,
},
{ withCredentials: true }
);
console.log(user);
},
getMe: async function() {
const me = await axios.get(`/api/v1/users/me`, {
withCredentials: false,
});
console.log(me);
},
},
};
</script>
You can see the two async methods; the 'getMe' method will still send cookies to the backend even if set false. The cookie is set from the backend on login, it's a httpOnly cookie with an JSON token in it for backend authentication. Obviously in the real world, I would want to send credentials; but I noticed it was sending cookies by default and when told false.
Is there something I am missing? If I use the Fetch() API and use "credentials: 'omit'" the cookies are not sent to the backend.
This is a brand new clean, VueJS 2 project created from the CLI. The only 'special' thing I am doing it a custom proxy so requests are proxied to the backend.
// vue.config.js;
module.exports = {
devServer: {
proxy: {
'/': {
target: 'http://localhost:3010',
},
},
},
};
If I console.log req.cookies in the backend on the GET request i get:
{
authToken: 'RANDOM JSON TOKEN'
}
withCredentials only applies to cross-origin requests (which have to ask for explicit permission (per the CORS specification) before including cookies).
Try configuring the client upfront explicitly, by setting "axios.defaults.withCredentials = false", instead of when making a call.
Also, i recall hearing that some JS frameworks overwrite this setting anyway, when assembling XMLHttpRequest object.
I am using the "Vue Stripe Checkout 3" component, and when I try to implement it, I get the following error "
Invalid value for Stripe (): apiKey should be a string. You specified: undefined.
In my data I have:
publishableKey: process.env.PUBLISHABLE_KEY,
Also I tried putting adding my key directly (publishableKey: 'my key') and it still didn't work. I also tried putting it in the prop directly and nothing.
<template>
<div>
<stripe-checkout
ref="checkoutRef"
:pk="publishableKey"
:items="items"
:successUrl="successUrl"
:cancelUrl="cancelUrl">
<template slot="checkout-button">
<button #click="checkout" class="btn-yellow wow fadeInUp btn" style="visibility: visible; animation-name: fadeInUp;">Pagar</button>
</template>
</stripe-checkout>
</div>
</template>
<script>
import { StripeCheckout } from 'vue-stripe-checkout';
export default {
components: {
StripeCheckout
},
data: () => ({
loading: false,
publishableKey: 'sk_test_51H85e2F5x69G5dDPxFEtO0RyIBWBEWkqwV9fpN5ovLysfCxJ15kfyeALoUFdZNi57yt0zj40h4LV3l5Zkra6WPCw00by0N0W3a',
items: [
{
sku: item.sku,
quantity: 1
}
],
successUrl: 'https://tarfut.es',
cancelUrl: 'https://tarfut.es',
}),
methods: {
checkout () {
this.$refs.checkoutRef.redirectToCheckout();
},
},
}
</script>
Thanks in advance.
I had a similar error in my Next.js app, which I've solved by type casting the key to a string.
Try replacing:
publishableKey: process.env.PUBLISHABLE_KEY,
with:
publishableKey: `${process.env.PUBLISHABLE_KEY}`,
This is due to the fact that your are not specifying to your nuxt application which env variable you want to set.
You have to precise in your nuxt.config.js which one needs to be accessible from production.
export default {
mode: 'universal',
env: {
API_BASE_URL: process.env.API_BASE_URL,
STRIPE_API_KEY: process.env.STRIPE_API_KEY,
GOOGLE_ANALYTICS: process.env.GOOGLE_ANALYTICS
...
},
...
Here is the official documentation.
I'm rather new to VueJS, and I would like to add a picture loaded from an API as a background image. However, the image loading eventually works.
Here is the code:
<template>
<div id="bio" :style="{ backgroundImage: 'url(' + this.settings.bio_bg.url +')' }">
<h1>Biography</h1>
<router-link to="/">Home</router-link><br />
<span>Biography</span><br />
<router-link to="/shop">Shop</router-link><br />
<router-link to="/contact">Contact</router-link><br />
</div>
</template>
<style scoped>
</style>
<script>
export default {
data () {
return {
settings: {},
bio: {}
}
},
created () {
.catch(error => this.setError(error))
this.$http.secured.get('/settings')
.then(response => {
this.settings = response.data
console.log(this.settings)
})
.catch(error => this.setError(error))
}
}
</script>
The image is loaded, but my console returns two errors:
Error in render: "TypeError: Cannot read property 'url' of undefined"
Cannot read property 'url' of undefined
I guess that since the Axios call is asynchronous, everything arrives after the page is done loading, but is still loaded after.
What would the proper way be to correctly wait for data to be available? I tried a few things that I know from React, but it doesn't load at all (even though the errors stop showing up)
Thank you in advance
Yo need to be sure that this.settings.bio_bg.url exist from the component birth, so compiler doesn't broke trying to render it. In order to do so, just setup a 'fake' url in the original data of the component:
export default {
data () {
return {
settings: {
bio_bg: {
url: '',
}
},
bio: {}
}
},
created () {
this.$http.secured.get('/settings')
.then(response => {
this.settings = response.data
console.log(this.settings)
})
.catch(error => this.setError(error))
}
}
This not only prevent errors, also provides better intellisense since now your code editor can now that settings has a bio_bg member which in turn has an url.
If instead of ' ', you provide a real image url with a placeholder img, probably the UI will be nicer:
data () {
return {
settings: {
bio_bg: {
url: 'http://via.placeholder.com/350x150',
}
},
bio: {}
}
}
I was using a Dribbble api v1 and it was successfully in feching data. Then it stoped to return because the v1 become deprecated. Later I made a new app version using the v2 api and I got a new 'access_token' and it continuing not showing.
Overview for the v2 Dribble API
https://developer.dribbble.com/v2/
When I put this URL in the browser:
https://api.dribbble.com/v2/user?access_token=1323213h23h2131j2h3jk12
it returns succefully my personal data from my account. It proves that my tolken is working.
But in my App I want to return popular shots from all users and it doesn' return nothing:
NOTE: This code was been working when I was using v1 Dribbble api. I made this using ReactJS but the Knowledge of this tool is not mandatory to understand the problem. It is something wrong that have to do with v2 Dribbble api.
export default class DribbblesList extends Component {
constructor(props) {
super(props);
this.state = { page: 1, shots: [], showModal: false };
this.getShots = this.getShots.bind(this);
}
componentDidMount() {
this.getShots();
}
getShots() {
this.setState({
dataFetched: false
})
return $.getJSON('https://api.dribbble.com/v2/shots?page=' +
this.state.page + '&access_token=sdfsdfsdfsdfsdfsdfsdf')
.then((resp) => {
var newShots = this.state.shots.concat(resp.data);
this.setState({
page: this.state.page + 1,
shots: newShots,
dataFetched: true
});
console.log(resp)
});
}
render() {
const shots = this.state.shots.map((data, i) => {
return (
<div>
<Dribbble data={data} key={i} />
</div>
)
});
Error Message: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 404.
Does anybody know how to solve it?
Thank you