Axios + Vue executing same POST twice - vue.js

While executing a POST in Axios, the request is always sent twice. This is not a CORS issue, as I get two pairs of requests (CORS and POST, and then ANOTHER CORS and POST).
I scaffolded a sample application using the hello-world template and it still exhibits the same behaviour:
<template>
<div class="hello">
Test
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'HelloWorld',
props: {
msg: String
},
mounted() {
axios.create({
baseURL: 'https://api.example.com'
}).post('/login', {
token: 'tokenString'
}).then((a) => {
console.log(a)
})
.catch((err) => {
console.log('err login')
console.log(err)
})
}
}
</script>
<style scoped>
</style>
I only get the console.log of the second request, but the network tab clearly shows the two pairs of requests, and the API also indicates that two POST requests (with exactly the same parameters) have been made...

This is actually a problem with an extension called Privacy Possum, so it has nothing to do with axios in particular.

Related

How to use router guard in nuxtjs

I am have been trying to get this to work, but it doesn't seem to work. I am trying to use the beforeRouteUpdate in my component in nuxt. What I want is for an api request to be made when I try to leave that page to another page. Here is my code;
<template>
<div>
//code here
</div>
</template>
<script>
export default {
beforeRouteUpdate(to, from, next) {
console.log('Before update')
},
}
</script>
In the code above, I am trying to log a message to the console when the route is updated, and nothing seems to happen. I tried making a request to the server when the route changes, that doesn't also work.
Tried using this other way;
<template>
<div>
//code here
</div>
</template>
<script>
export default {
watch: {
$route(to, from) {
console.log('Route path')
},
},
}
</script>
It still doesn't work. The current path is http://localhost:3000/cart. I am trying to console.log a message when the path changes to http://localhost:3000/ or something else.
I don't know if I am doing something wrong.
I am using console.log in this case for simplicity
Instead of beforeRouteUpdate use beforeRouteLeave:
<template>
<div>
//code here
</div>
</template>
<script>
export default {
beforeRouteLeave(to, from, next) {
console.log('Route Leave')
},
}
</script>

Returning json data from url with Vue.js

I am working on a simple app that returns one value from a json resource at certain url.
Although I've created a vue.config.js file to avoid CORS problem, still getting on execution the message:
Access to fetch at 'https://api.darksky.net/forecast/xxx/37.8267,-122.4233' from origin 'http://localhost:8080' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
What am I missing? Thank you very much!
Location.vue
<template>
<div>
<h1>{{ forecast.timezone }}</h1>
</div>
</template>
<script>
export default {
name: 'Location',
props: {
forecast: Array
}
}
</script>
App.vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<location v-bind:forecast="forecast" />
</div>
</template>
<script>
import Location from './components/Location.vue'
export default {
name: 'App',
components: {
Location
},
data() {
return {
forecast: []
}
},
mounted() {
this.getTimeZone()
},
methods: {
async getTimeZone() {
try {
const response = await fetch('https://api.darksky.net/forecast/xxx/37.8267,-122.4233')
const data = await response.json()
this.forecast = data
} catch (error) {
console.error(error)
}
}
}
}
</script>
vue.config.js
module.exports = {
devServer: {
proxy: 'https://api.darksky.net/forecast/xxx/'
}
}
You need to setup CORS policy for external API. It's not related to vue.js.
Alternatively, if the external API is a 3rd-party API and you cannot change the CORS policy, then you can consume the external API in your server-side code and create your own API in your server-side code that will return whatever value you get from the external API.
From Vue Cli docs:
WARNING
When devServer.proxy is set to a string, only XHR requests will be proxied. If you want to test an API URL, don't open it in the browser, use an API tool like Postman instead.
So, setting the devServer.proxy property, does not solve the issue, as api requests won't be proxied. For a permanent solution, as Circuit Breaker suggested, you have to allow the CORS request on the api server.

Nuxtjs: Best way to show data in page header

I started to use Nuxt.js for SSR purposes. In the header I have a navigation menu which it's items should be requested from server side.
Here is default.vue
<template>
<div>
<app-header></app-header>
<nuxt />
<app-footer></app-footer>
</div>
</template>
<script>
import Header from '~/components/Header.vue'
import Footer from '~/components/Footer.vue'
export default {
components: {
'app-header': Header,
'app-footer': Footer,
}
}
</script>
So, what is the best way to fetch items and prevent sending request on every single page?
I thought of using Vuex to store this data. But I don't if it's a good solution or not.
You can use Vuex and declare your navbar items inside the store.
state: {
navbarItems: []
},
mutations: {
FETCH_ITEMS(state, navbarItems) {
state.navbarItems = navbarItems
}
},
actions: {
fetchItems({ commit }) {
Vue.http.get("your api here ") // or axios
.then((response) => {
commit("FETCH_ITEMS", response.body);
})
.catch((error => {
console.log("error")
}))
}
And inside your header
created() {
this.$store.dispatch("fetchItems")
}
Thanks

Rails API responding to request, but axios not retrieving data

I have a Rails 5.2.2 API that is serving JSON data at localhost:3000/v1/stories. I am trying to set up a Vuejs app to consume it with Axios. The rails terminal shows the request and throws no errors:
Started GET "/v1/stories" for 127.0.0.1 at 2018-12-19 18:06:44 -0500
Processing by V1::StoriesController#index as HTML
Story Load (0.8ms) SELECT "stories".* FROM "stories"
↳ app/controllers/v1/stories_controller.rb:6
[active_model_serializers] Rendered ActiveModel::Serializer::CollectionSerializer with ActiveModelSerializers::Adapter::JsonApi (6.25ms)
Completed 200 OK in 10ms (Views: 8.7ms | ActiveRecord: 0.8ms)
MyIn the vue app, I have the following relevant files:
Api.js retrieves the base connection:
import axios from 'axios'
export default() => {
return axios.create({
baseURL: `http://localhost:3000/v1`
headers: {
'Accept': 'applicaton/json',
'Content-Type': 'application/json'
}
})
}
StoriesService.js:
import Api from '#/services/Api'
export default {
fetchStories () {
return Api().get('/stories')
}
}
and in the view (components/Stories.vue):
<template>
<div class="stories">
<h1>Stories</h1>
<div v-if="stories" class="table-wrap">
<div v-for="story in stories" :key="story.id">
<h3>Title: {{story.title}}</h3>
<p>Summary: {{story.description}}</p>
</div>
</div>
<div v-else>
There are no stories... Let's add one now <br><br>
<!-- <router-link v-bind:to="{ name: 'NewStory' }" class="add_story_link">Add Story</router-link> -->
</div>
</div>
</template>
<script>
import StoriesService from '#/services/StoriesService'
export default {
data () {
return {
stories: []
}
},
mounted () {
this.getStories()
},
methods: {
async getStories () {
const response = await StoriesService.fetchStories()
this.stories = response.data.stories
}
}
}
</script>
In the Rails app, cors.rb is:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*',
:headers => :any,
methods: %i(get post put patch delete options head)
end
end
I made the suggested adjustment. here is the response from the GET request to the back end in the. It shows the data coming through, but for some reason, it does not display from the v-for loop.
Your Rails API endpoint is returning the stories array assigned to a data property, eg
{
"data":[...]
}
The response body object is assigned to response.data via Axios so what you actually want is
this.stories = response.data.data

adding headers to nuxt for making api rest call with axios

Inside my nuxt application i need to make call to an external api like this (file.vue) :
<template>
<div class="container">
<h1>{{ post.title }}</h1>
<pre>{{ post.body }}</pre>
<p><nuxt-link to="/posts">Back to the list</nuxt-link></p>
</div>
</template>
<script>
export default {
async asyncData({ app }) {
let { data } = await app.$axios.$get(`http://my.api.adress:8001/competition/sport/4?_format=json&limit=20&offset=0`)
return { post: data }
},
head() {
return {
title: this.post.title
}
}
}
</script>
To make this call works i need to pass tree arguments to my headers. Anyone has an idea on how to do that to make it work for all api call in nuxt ?
You can set headers using the axios module for nuxt (which you already do).
Taken from their documentation:
setHeader(name, value, scopes='common')
name: Name of the header
value: Value of the header
scopes: Send only on specific type of requests.
Examples:
// Adds header: `Authorization: 123` to all requests
this.$axios.setHeader('Authorization', '123')
// Overrides `Authorization` header with new value
this.$axios.setHeader('Authorization', '456')
// Adds header: `Content-Type: application/x-www-form-urlencoded` to only
// post requests
this.$axios.setHeader('Content-Type', 'application/x-www-form-urlencoded', [
'post'
])
// Removes default Content-Type header from `post` scope
this.$axios.setHeader('Content-Type', false, ['post'])
Please refer to the documentation for more information: https://github.com/nuxt-community/axios-module#setheadername-value-scopescommon